Java 中的Map集合的讲解

Map集合概述

首先对比一下Map接口和Collection接口

// Collection集合,有一个泛型<E>
public interface Collection<E> extends Iterable<E> { ... }

// Map集合,有两个泛型<K, V>
public interface Map<K,V> { ... }

在Collection集合中,E映射的是值的类型。在Map集合中,K映射的是键的类型,V映射的是值的类型。

简单的说,Map集合是一个将键(Key)映射到值(Value)的对象。且一个映射不能包含重复的键;每个键只能映射到一个值。

Map接口提供三种collection视图,允许以Key集、Value集、Key-Value映射关系的形式查看某个映射的内容。映射顺序定义为迭代器在映射的collection视图上返回其元素的顺序。

那什么是映射呢?在生活中,我们常常会看到这样的一种集合:账号——密码、IP地址——主机名、系统用户名——系统用户对象等。像这种一一对应的关系,就叫做映射。在Java中,Map类就是如此,专门用来存放这种对象关系的对象。

Map集合与Collection集合的区别

1、collection中的集合,元素是孤立存在的(单身狗),向集合中存储元素采用一个个元素的方式存储。

2、map中的集合,元素是成对存在的(情侣、夫妻),每个元素由键(key)与值(value)两个部分组成,通过键可以找到其所对应的值。

3、collection中的集合成为单列集合,map中的集合称为双列集合。

4、Collection接口的底层是由哈希表或哈希表+链表实现的。

5、Map接口的底层是由哈希表和链接列表实现的

简单总结一下Map集合的特点

1、Map集合是一个双列集合,一个元素包含两个值(一个key,一个value)。

2、Map集合中的元素,key和value的数据类型可以相同,也可以不同。

3、Map集合中的元素,key是不允许重复的, value是可以重复的。

4、Map集合中的元素,key和 value是一一对应的。

Map接口常用的方法

public V put(K key, V value):把指定的键与指定的值添加到Map集合中。

public V remove(Object key):把指定的键所对应的键值对元素在Map集合中删除,返回被删除元素的值

public V get(Object key):根据指定的键,在Map集合中获取对应的值。

boolean containsKey(Object key):判断集合中是否包含指定的键。

public Set<K> keySet():获取Map集合中所有的键,存储到Set集合中。

public Set<Map. Entry<K,V> entrySet():获取到Map集合中所有的键值对对象的集合(Set集合)。

下面对这几个方法进行简单的举例,首先说明一下,HashMap类是Map接口的实现类

put()方法

说明:

public V put(K key, V value)
作用:
把指定的键与指定的值添加到Map集合中。 注意:
1、当要添加的key不存在的时候,调用put方法后,map集合中会添加新的
<Key-Value>,添加成功会返回null。 2、当要添加的key存在的时候,调用put方法后,会使用新的Value替换map集合中旧的Value,替换成功会返回旧的Value。

例子1:

import java.util.HashMap;
import java.util.Map;

public class DemoMapPut {
    public static void main(String[] args) {
        // 用多态的形式,创建一个hashMap集合,集合长度为16
        Map<String, String> hashMap = new HashMap<>(16);

        // 使用Map接口的特有方法put方法,向集合中添加<key-value>
        String return0 = hashMap.put("杨过", "小龙女");
        String return1 = hashMap.put("过儿", "姑姑");
        System.out.println("返回值0:" + return0);
        System.out.println("返回值1:" + return1);
        System.out.println("Map集合:" + hashMap);
    }
}
输出结果:
返回值0:null
返回值1:null
Map集合:{杨过=小龙女, 过儿=姑姑}

例子2:

import java.util.HashMap;
import java.util.Map;

public class Demo02MapPut {
    public static void main(String[] args) {
        Map<String, String> hashMap = new HashMap<>(16);

        String return0 = hashMap.put("杨过", "小龙女");
        String return1 = hashMap.put("杨过", "姑姑");

        System.out.println("返回值0:" + return0);
        System.out.println("返回值1:" + return1);
        System.out.println("Map集合:" + hashMap);
    }
}
输出结果:
返回值0:null
返回值1:小龙女
Map集合:{杨过=姑姑}

remove()方法

说明:

public V remove(Object key)
作用:把指定的键所对应的键值对元素在Map集合中删除,返回被删除元素的值。
注意:
1、key存在,删除对应元素,并返回被删除的值
2、key不存在,返回null

例子:

import java.util.HashMap;
import java.util.Map;

public class Demo01MapRemove {
    public static void main(String[] args) {
        Map<String, String> hashMap = new HashMap<>(16);

        hashMap.put("key0", "value0");
        hashMap.put("key1", "value1");
        hashMap.put("key2", "value2");
        System.out.println("没有调用remove方法前的Map集合:" + hashMap);

        String return0 = hashMap.remove("key0");
        String return1 = hashMap.remove("key666");
        System.out.println("返回值0:" + return0);
        System.out.println("返回值1:" + return1);
        System.out.println("调用remove方法后的Map集合:" + hashMap);
    }
}
输出结果:
没有调用remove方法前的Map集合:{key1=value1, key2=value2, key0=value0}
返回值0:value0
返回值1:null
调用remove方法后的Map集合:{key1=value1, key2=value2}

get()方法

说明:

public V get(Object key)
作用:根据指定的键,在Map集合中获取对应的值。
注意:
1、key存在,并返回对应Value值
2、key不存在,返回null

例子:

import java.util.HashMap;
import java.util.Map;

public class Demo01MapGet {
    public static void main(String[] args) {
        Map<String, Integer> hashMap = new HashMap<>(16);

        hashMap.put("Aa", 18);
        hashMap.put("Bb", 20);

        System.out.println("key是'Aa'对应的Value是:" + hashMap.get("Aa"));
        System.out.println("key是'BB'对应的Value是:" +hashMap.get("BB"));
    }
}
输出结果:
key是'Aa'对应的Value是:18
key是'BB'对应的Value是:null

containsKey()方法

说明:

boolean containsKey(Object key)
作用:判断集合中是否包含指定的键。
返回值:
1、key存在的情况下,返回true
2、key不存在的情况下,返回false

例子:

import java.util.HashMap;
import java.util.Map;

public class Demo01MapContainsKey {
    public static void main(String[] args) {
        Map<String, Integer> hashMap = new HashMap<>(16);

        hashMap.put("k1", 100);
        hashMap.put("k2", 200);
        System.out.println("hashMap集合:" + hashMap);

        boolean response1 = hashMap.containsKey("k1");
        boolean response2 = hashMap.containsKey("k999");
        System.out.println("是否存在键值为'k1'的元素:" + response1);
        System.out.println("是否存在键值为'k999'的元素:" + response2);
    }
}
输出结果:
hashMap集合:{k1=100, k2=200}
是否存在键值为'k1'的元素:true
是否存在键值为'k999'的元素:false

keySet()方法

说明:

public Set<K> keySet()
作用:获取Map集合中所有的键,存储到Set集合中。
返回值:返回Map集合中所有的Key的一个集合对象。

例子:

import java.util.Map;
import java.util.HashMap;
import java.util.Set;

public class Demo01MapKeySet {
    public static void main(String[] args) {
        Map<String, Integer> hashMap = new HashMap<>(16);

        hashMap.put("k1", 1);
        hashMap.put("k2", 2);
        hashMap.put("k3", 3);
        hashMap.put("k4", 4);
        hashMap.put("k5", 5);
        hashMap.put("k6", 6);
        System.out.println("hashMap:" + hashMap);

        // 使用keySet()方法,获取Map集合中所有的键,存储到Set集合中。
        Set<String> set = hashMap.keySet();

        // 输出set集合
        System.out.println("set:" + set);
    }
}
输出结果:
hashMap:{k1=1, k2=2, k3=3, k4=4, k5=5, k6=6}
set:[k1, k2, k3, k4, k5, k6]

entrySet()方法

说明:

public Set<Map. Entry<K,V> entrySet()
作用:获取到Map集合中所有的键值对对象的集合(Set集合)。
返回值:返回值是一个key-value的Set集合对象
注意:由于Map集合中有两个泛型(K, V),Set集合中只有一个泛型,所以不能直接赋值给Set对象,但可以通过Map.Entry的方式赋值给Set对象

如:

抛出错误: 

 或者又如:

 抛出错误

赋值给Set集合对象:

entrySet方法举例:

import java.util.HashMap;
import java.util.Map;

public class Demo01MapEntrySet {
    public static void main(String[] args) {

        Map<String, String> hashMap = new HashMap<>(16);

        hashMap.put("k1", "1");
        hashMap.put("k2", "2");
        hashMap.put("k3", "3");
        hashMap.put("k4", "4");
        hashMap.put("k5", "5");
        hashMap.put("k6", "6");
        System.out.println("hashMap:" + hashMap);

        // 调用entrySet方法,获取到Map集合中所有的键值对对象的集合
        System.out.println("键值对对象的集合:" + hashMap.entrySet());
    }
}
输出结果:
hashMap:{k1=1, k2=2, k3=3, k4=4, k5=5, k6=6}
键值对对象的集合:[k1=1, k2=2, k3=3, k4=4, k5=5, k6=6]

Map集合遍历键(key)的方式找值(Value)

1、通过Map集合的keySet()方法,获取Map集合中所有的Key,存储到Set集合中

2、遍历Set集合,获取每个Key所对应的Value

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class Demo01MapIteratorKey {
    public static void main(String[] args) {
        Map<String, Integer> hashMap = new HashMap<>(16);

        hashMap.put("k1", 1);
        hashMap.put("k2", 2);
        hashMap.put("k3", 3);
        hashMap.put("k4", 4);
        hashMap.put("k5", 5);
        hashMap.put("k6", 6);
        System.out.println("hashMap:" + hashMap);

        Set<String> sKey = hashMap.keySet();

        // 获取Set集合的迭代器对象,并遍历该迭代器对象
        Iterator<String> ite = sKey.iterator();
        while (ite.hasNext()) {
            // 通过迭代器对象中的每一个值(Map集合中的键),获取key-value
            System.out.println(
                    "Key:" + ite.next() +
                    "    Value:" + hashMap.get(ite.next())
            );
        }
    }
}
输出结果:
hashMap:{k1=1, k2=2, k3=3, k4=4, k5=5, k6=6}
Key:k1    Value:2
Key:k3    Value:4
Key:k5    Value:6

Map集合遍历键值对方式

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class Demo01MapIteratorKeyValue {
    public static void main(String[] args) {
        Map<String, Integer> hashMap = new HashMap<>(16);

        hashMap.put("k1", 1);
        hashMap.put("k2", 2);
        hashMap.put("k3", 3);
        hashMap.put("k4", 4);
        hashMap.put("k5", 5);
        hashMap.put("k6", 6);
        System.out.println("hashMap:" + hashMap);

        Set<Map.Entry<String, Integer>> keyValue = hashMap.entrySet();

        // 获取Set集合的迭代器对象,并遍历该迭代器对象
        Iterator<Map.Entry<String, Integer>> ite = keyValue.iterator();
        while (ite.hasNext()) {
            // 通过Entry对象的getKey()和getValue()方法,获取Key和Value
            Map.Entry<String, Integer> kv = ite.next();
            System.out.println(
                    "Key:" + kv.getKey() +
                            "    Value:" + kv.getValue()
            );
        }
    }
}
输出结果:
hashMap:{k1=1, k2=2, k3=3, k4=4, k5=5, k6=6}
Key:k1    Value:1
Key:k2    Value:2
Key:k3    Value:3
Key:k4    Value:4
Key:k5    Value:5
Key:k6    Value:6

HashMap存储自定义类型的键值

注意:Map集合,要保证Key是唯一的。作为Key的元素,必须重写hashCode()方法和equals()方法,才能保证Key的唯一性

代码理解

创建一个Student类,用左Map中Key的数据类型:

public class Student {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    
}

创建两个方法:

方法1使用<String, String>为<key, value>的数据类型

方法2使用<Student, String>为<key, value>的数据类型

import java.util.HashMap;
import java.util.Map;

public class MapRepeat {

    /**
     * String类型已经重写了hashCode()方法和equals()方法
     * 可以保证key唯一
     */
    public static void method01() {
        Map<String, String> map = new HashMap<>(16);
        map.put("k1", "v1");
        map.put("k2", "v2");
        map.put("k3", "v3");
        map.put("k4", "v4");
        map.put("k1", "v5");
        System.out.println(map);
    }

    /**
     * Student类型没有重写hashCode()方法和equals()方法
     * 不能保证key唯一
     */
    public static void method02() {
        Map<Student, String> map = new HashMap<>(16);
        map.put(new Student("学生1", 22), "v1");
        map.put(new Student("学生2", 18), "v2");
        map.put(new Student("学生3", 19), "v3");
        map.put(new Student("学生4", 21), "v4");
        map.put(new Student("学生1", 22), "v5");
        System.out.println(map);
    }

}

比较这两个方法:

public class Demo01MapRepeat {
    public static void main(String[] args) {
        // Map<String, String>,String类已经重写了hashCode()方法和equals()方法
        MapRepeat.method01();
        // Map<Student, String>,Student类没有重写了hashCode()方法和equals()方法
        MapRepeat.method02();
    }
}
输出结果:
{k1=v5, k2=v2, k3=v3, k4=v4}
{Student{name='学生1', age=22}=v1, Student{name='学生1', age=22}=v5, Student{name='学生2', age=18}=v2, Student{name='学生4', age=21}=v4, Student{name='学生3', age=19}=v3}

可以看到,方法1输出的集合,并没有重复的Key,而方法2输出的集合存在冲的的Key。

其中重复的Key是Student{name='学生1', age=22}

在Student类中重写hashCode()方法和equals()方法

// 在Student类添加如下代码

import java.util.Objects;

public class Student {

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Student student = (Student) o;
        return age == student.age &&
                Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}
那么对MapRepeat.method02()测试,输出结果则是:
{Student{name='学生4', age=21}=v4, Student{name='学生2', age=18}=v2, Student{name='学生3', age=19}=v3, Student{name='学生1', age=22}=v5}

可以看出,与没有重写hashCode()方法和equals()方法前相比,重写后,不存在重复的key了。

LinkedHashMap集合简单了解

说明:

LinkedHashMap类是HashMap的子类,
LinkedHashMap底层采用的是哈希表+链表结构,LinkedHashMap集合是有存取顺序的集合,而其父类HashMap是没有存取顺序的集合

例子:

import java.util.Map;
import java.util.HashMap;
import java.util.LinkedHashMap;

public class DemoLinkedHashMap {
    public static void main(String[] args) {

        // 无序Map集合:HashMap
        Map<Integer, Integer> hashMap = new HashMap<>(16);
        hashMap.put(1, 200);
        hashMap.put(3, 400);
        hashMap.put(5, 600);
        hashMap.put(2, 100);
        hashMap.put(4, 300);
        hashMap.put(6, 500);
        System.out.println(hashMap);

        // 有序Map集合:LinkedHashMap
        Map<Integer, Integer> linked = new LinkedHashMap<>(16);
        linked.put(1, 200);
        linked.put(3, 400);
        linked.put(5, 600);
        linked.put(2, 100);
        linked.put(4, 300);
        linked.put(6, 500);
        System.out.println(linked);

    }
}
输出结果:
{1=200, 2=100, 3=400, 4=300, 5=600, 6=500}
{1=200, 3=400, 5=600, 2=100, 4=300, 6=500}

Hashtable集合的简单了解

说明:

java.utiL.Hashtable<k, v>集合 implements Map<K,V>接口Hashtable:底层也是一个哈希表,是一个线程安全的集合,是单线程集合,速度慢
HashMap:底层是一个哈希表,是一个线程不安全的集合,是多线程的集合,速度快
ArrayList集合、LinkedList集合、HashSet集合、HashMap集合等:可以存储null值【null键】
Hashtable集合,不能存储null值,null键
Hashtable和Vector集合一样,在jdk1.2版本之后被更先进的集合( HashMap、 ArrayList)取代了
Hashtable的子类 Properties依然活跃在历史舞台
Properties集合是一个唯一和I0流相结合的集合

Hashtable传入null,抛出错误

 例子:

import java.util.HashMap;
import java.util.Hashtable;

public class DemoHashTable {
    public static void main(String[] args) {
        HashMap<String, String> hashMap = new HashMap<>(16);
        hashMap.put(null, null);
        hashMap.put(null, "A");
        hashMap.put("A", null);
        hashMap.put("B", "B");
        System.out.println("hashMap:" + hashMap);

        Hashtable<String, String> hashtable = new Hashtable<>(16);
        // Hashtable集合,key和value都不能是null
        // 如果传入空值,会抛出错误:空指针异常(NullPointerException)
        // hashtable.put(null, null);
        // hashtable.put(null, "A");
        // hashtable.put("A", null);
        hashtable.put("B", "B");
        System.out.println("hashtable:" + hashtable);
    }
}
输出结果:
hashMap:{null=A, A=null, B=B}
hashtable:{B=B}

猜你喜欢

转载自www.cnblogs.com/liyihua/p/12199448.html