Java教程

Java集合框架——Map

本文主要是介绍Java集合框架——Map,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

Map

  • 一、Map接口简述
  • 二、 Map中定义的方法
    • 2.1 添加、删除、修改
    • 2.2 元素查询的操作:
    • 2.3 元视图操作的方法:
  • 三、 Map实现类
    • 3.1 HashMap
      • 3.1.1 LinkedHashMap
    • 3.2 TreeMap
      • 3.2.1 Tree的两种添加方式
        • 自然排序
        • 定制排序
    • 3.3 Hashtable
      • 3.3.1 Properties
      • jdk8
    • 4.2 HashMap和Hashtable的异同?

一、Map接口简述

存储双列数据,存储key-value对的数据 ----类似于高中讲的函数

  • Map结构的理解:
    Map中的key:无序、不可重复,使用Set存储所有的key —>要求key所在类重写equals()方法和hashCode()方法
    Map中的value:无序、可重复使用Collection存储所有的value —>value所在类要重写equals()方法
    一个键值对:key-value构成了一个Entry对象。
    Map中的Entry:无序、不可重复,使用Set存储所有的Entry

二、 Map中定义的方法

2.1 添加、删除、修改

  • object put(Object key,object value):将指定 key-value添加到(或修改)到当前map对象中
    public void  putTest(){

        HashMap map = new HashMap();

        //添加
        map.put("A",'a');
        map.put("B",'b');
        map.put("C",'c');
        map.put("D",'d');
        map.put("E",'e');
        System.out.println(map);

        //修改
        map.put("A","aa");
        System.out.println(map);

    }

输出

{A=a, B=b, C=c, D=d, E=e}
{A=aa, B=b, C=c, D=d, E=e}
  • void putAll(Map m):将m中的所有 key-value对存放到当前map中
    public void  test(){

        HashMap map = new HashMap();

        //添加
        map.put("A",'a');
        map.put("B",'b');
        map.put("C",'c');
        map.put("D",'d');
        map.put("E",'e');
        System.out.println(map);

        HashMap map1 = new HashMap();
        map1.putAll(map);
        System.out.println(map1);

    }

输出:

{A=a, B=b, C=c, D=d, E=e}
{A=a, B=b, C=c, D=d, E=e}
  • Object remove(Object key):移除指定key的key-value对,并返回value
        System.out.println(map.remove("A"));
        System.out.println(map.remove("a"));
        System.out.println(map);

输出:

aa
null
{B=b, C=c, D=d, E=e}
  • void clear:清空当前map中的所有数据
        map.clear();
        System.out.println(map);
        System.out.println(map.size());

输出:

{}
0

2.2 元素查询的操作:

Object get(Object key):获取指定key对应的value

        System.out.println(map.get("D"));
        System.out.println(map.get("DD"));
d
null

boolean containsKey(Object key):是否包含指定的key

        System.out.println(map.containsKey("E"));
        System.out.println(map.containsKey("EE"));
true
false

boolean containsValue(Object value):是否包含指定的value

        System.out.println(map.containsValue("a"));
        System.out.println(map.containsValue('a'));
        System.out.println(map.containsValue("asbha"));
false
true
false

int size();返回map中的 key-value 的个数

        System.out.println(map.size());
5

boolean isEmpty():判断当前map是否为空

        System.out.println(map.isEmpty());
        map.clear();
        System.out.println(map.isEmpty());
false
true

boolean equals(Object obj):判断当前map和参数对象obj是否相等

        HashMap map1 = new HashMap();

        //添加
        map1.put("A",'a');
        map1.put("B",'b');
        map1.put("C",'c');
        map1.put("D",'d');
        map1.put("E",'e');

        System.out.println(map.equals(map1));

        HashMap map2 = new HashMap();

        //添加
        map2.put("A",'a');
        map2.put("B",'c');
        map2.put("C",'c');
        map2.put("D",'d');
        map2.put("E",'e');

        System.out.println(map.equals(map2));
true
false

2.3 元视图操作的方法:

Set keySet():返回所有key构成的Collection集合
Collection values():返回所有value构成的Collection集合
Set entrySet():返回所有key-value对构成的Set集合

        HashMap map = new HashMap();

        //添加
        map.put("A",'a');
        map.put("B",'b');
        map.put("C",'c');
        map.put("D",'d');
        map.put("E",'e');
//遍历
//        `` Set keySet()``:返回所有key构成的Collection集合
        Set set = map.keySet();
        Iterator iterator = set.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }

        System.out.println("####");

//        ``Collection values()``:返回所有value构成的Collection集合
        Collection values = map.values();
        for (Object obj : values){
            System.out.println(obj);
        }

        System.out.println("####");

//        ``Set entrySet()``:返回所有key-value对构成的Set集合
        Set entrySet = map.entrySet();
        Iterator iterator1 = entrySet.iterator();
        while (iterator1.hasNext()){
            Object obj = iterator1.next();
            //entrySet集合中的元素都是entry
            Map.Entry entry = (Map.Entry) obj;
            System.out.println(entry.getKey() + "--->" + entry.getValue());
        }
A
B
C
D
E
####
a
b
c
d
e
####
A--->a
B--->b
C--->c
D--->d
E--->e

三、 Map实现类

3.1 HashMap

作为Map的主要实现类
HashMap是线程不安全的,但是效率高
可以存储null的key或者value

HashMap底层:数组+链表(jdk7及以前),数组+链表+红黑树(jdk8)

3.1.1 LinkedHashMap

保证在遍历Map元素时,可以按照添加的顺序实现遍历

原因:在原有的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个元素
对于频繁的遍历操作,此类执行效率高于HashMap

3.2 TreeMap

保证按照添加的key-value对进行排序,实现遍历排序。此时考虑key的自然排序,或者定制排序
底层使用红黑树

3.2.1 Tree的两种添加方式

  • 向TreeMap中添加key-value,要求key必须是由同一个类创建的对象,一位key是排序的依据
    public void test1(){
        TreeMap map = new TreeMap();
        map.put("AA", 'a');
        map.put(1,'c');
    }

报错信息:

java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer

自然排序

    @Test
    public void test1(){
        TreeMap map = new TreeMap();

        User u1 = new User("Tom", 19);
        User u2 = new User("Alice", 51);
        User u3 = new User("Bob", 19);
        User u4 = new User("Jerry", 23);
        User u5 = new User("Jimi", 25);

        map.put(u1,98);
        map.put(u2,45);
        map.put(u3,65);
        map.put(u4,18);
        map.put(u5,54);

        Set entrySet = map.entrySet();
        Iterator iterator1 = entrySet.iterator();
        while (iterator1.hasNext()){
            Object obj = iterator1.next();
            //entrySet集合中的元素都是entry
            Map.Entry entry = (Map.Entry) obj;
            System.out.println(entry.getKey() + "--->" + entry.getValue());
        }
    }
    

输出:

User{name='Tom', age=19}--->98
User{name='Jimi', age=25}--->54
User{name='Jerry', age=23}--->18
User{name='Bob', age=19}--->65
User{name='Alice', age=51}--->45

定制排序

    @Test
    public void test2(){
        TreeMap map = new TreeMap(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                if(o1 instanceof User && o2 instanceof User){
                    User u1 = (User) o1;
                    User u2 = (User) o2;

                    return  Integer.compare(u1.getAge(),u2.getAge());
                }
                throw new RuntimeException("输入的类型不匹配");
            }
        });

        User u1 = new User("Tom", 19);
        User u2 = new User("Alice", 51);
        User u3 = new User("Bob", 19);
        User u4 = new User("Jerry", 23);
        User u5 = new User("Jimi", 25);

        map.put(u1,98);
        map.put(u2,45);
        map.put(u3,65);
        map.put(u4,18);
        map.put(u5,54);

        Set entrySet = map.entrySet();
        Iterator iterator1 = entrySet.iterator();
        while (iterator1.hasNext()){
            Object obj = iterator1.next();
            //entrySet集合中的元素都是entry
            Map.Entry entry = (Map.Entry) obj;
            System.out.println(entry.getKey() + "--->" + entry.getValue());
        }
    }

输出:

User{name='Tom', age=19}--->65
User{name='Jerry', age=23}--->18
User{name='Jimi', age=25}--->54
User{name='Alice', age=51}--->45

3.3 Hashtable

作为古老的实现类
线程安全,但是效率低
不能存储null的key或者value

3.3.1 Properties

常用来处理配置文件。key和value都是String类型

应用场景
配置文件jdbc.properties

name=Tom
password=abc123

java文件

    public static void main(String[] args) {
        
        FileInputStream fis = null;
        try {

            Properties pros = new Properties();

            fis = new FileInputStream("jdbc.properties");
            pros.load(fis);//加载对应的文件
            String name = pros.getProperty("name");
            String password = pros.getProperty("password");

            System.out.println("name = " + name + ",password = " + password);

        }catch (IOException e){
            e.printStackTrace();
        }finally {
            if(fis != null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

输出:

name = Tom,password = abc123
# 四、Map相关面试题
## 4.1 HashMap底层实现原理?
### jdk7
```javascript
HashMap map = new HashMap();
//在实例化后,底层创建了长度是16的一维数组Entry[] table
map.put(key1,value1);
//首先计算key1所在类的hashCode方法计算key1哈希值,此哈希值结果某种计算后得到在Entry数组中的存放位置
//如果此位置上的数据为空,此时的key1-value1 添加成功
//如果此位置上的数据不为空,(意味着,此位置上,存在一个或多个数据(以链表的形式存在)),比较key1和已经存在的数据的哈希值:
				//如果key1的哈希值与已经存在的数据的哈希值都不同,此时key1-value1就添加成功
				//如何key1的哈希值和已经存在的某一个数据(key2-value2)的哈希值相同,继续比较:调用key1所在类的equals(key2)方法比较:
						//如何返回false:此时key1-value1添加成功
						//如果返回true:使用value1替换value2
//
//

不断地添加过程中,会涉及到扩容问题,默认的扩容方式:扩容为原来容量的2倍,并将原有的数据复制过来

jdk8

  • jdk8底层的数组是:Node[],而非Entry[]
  • 首次调用put方法时,底层创建长度为16的数组
  • jdk7底层结构只有:数组+链表。jdk8中底层结构:数组+链表+红黑树
    当数组的某一个多余位置上的元素以链表形式存储的数据个数 > 8 ,且当前数组的长度 > 64时,此时此索引位置上的所有数据改为红黑树存储(jdk8中的核心修改
new HashMap()//底层没有创建一个长度为16的数组

4.2 HashMap和Hashtable的异同?

这篇关于Java集合框架——Map的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!