Java集合之Map集合详细解释

Map双列集合结构

Map是采用key-value键值对存储数据的,一个key对应一个值,对于key不可重复,value可以重复,主要的实现类有HashMap,LinkedHashMap,TreeMap,HashTable

HashMap

Map集合中最常用的实现类

常用方法
  • 添加功能:
    V put(K key,V value):添加元素(也可以实现修改功能)
  • 删除功能:
    void clear():清空所键值对元素
    V remove(Object key):根据键移除对应的值,并把值返回
  • 判断功能:
    containsKey(Object key):是否包含指定的键
    containsValue(Object value):是否包含指定的值
    isEmpty():是否为空
  • 遍历功能:
    Set<Map.Entry<K,V>> entrySet():获取键值对
    V get(Object key):根据键获取值
    Collection values():获取所值的集合
  • 获取功能:
    Set keySet():获取所键的集合
    int size():获取集合元素的个数
使用这些方法
    //创建map集合
    HashMap<Integer, String> map = new HashMap<>();
    //添加元素
    map.put(1, "a");
    map.put(2, "b");
    map.put(3, "C");
    //键有重复值发生覆盖
    map.put(3, "C");
    //通过键删除整个键值对
    //map.remove(1);
    //清空
    //map.clear();
    //判断是否为空
    System.out.println(map.isEmpty());//f
    //是否包含key = 4
    System.out.println(map.containsKey(4));//f
    //是否包含"b"
    System.out.println(map.containsValue("b"));//t
    //集合元素个数
    System.out.println(map.size());//3
    //通过键获取值
    System.out.println(map.get(3));//C
    //获取所有值组成的集合,打印输出
    Collection<String> s = map.values();
    for (String value : s) {
    
    
        System.out.println(value);
    }
    System.out.println(map);	
    }
Map常见的遍历方式

第一种遍历方式:最常用的遍历方式,for循环中使用entries实现遍历

    HashMap<String, Integer> map = new HashMap<>();
    map.put("张三", 12);
    map.put("李四", 34);
    map.put("王五", 24);
    //第一种遍历方式
    for(Map.Entry<String, Integer> entry: map.entrySet()) {
    
    
        //获取key
        String key = entry.getKey();
        //获取value
        Integer value = entry.getValue();
        System.out.println(key + "--" + value);
    }

第二种方式:使用迭代器进行遍历

		HashMap<String, Integer> map = new HashMap<>();
		map.put("张三", 12);
		map.put("李四", 34);
		map.put("王五", 24);
		//使用迭代器进行遍历
		Iterator<Entry<String, Integer>> it = map.entrySet().iterator();
		while(it.hasNext()) {
    
    
			Entry<String, Integer> en = it.next();
			String key = en.getKey();
			Integer value = en.getValue();
			System.out.println(key+"---"+value);
		}

第三种方式:分开遍历key与value,只需要key或者是value来使用

// TODO Auto-generated method stub
		HashMap<String, Integer> map = new HashMap<>();
		map.put("张三", 12);
		map.put("李四", 34);
		map.put("王五", 24);
		//第三种方式遍历只需要key或者value
		for(String key:map.keySet()) {
    
    
			System.out.println(key);
		}
		for(Integer value: map.values()) {
    
    
			System.out.println(value);
		}
HashMap底层实现原理

JDK1.8之前 数组+链表

  • 实例化HashMap之后,底层先创建长度为16的Entry[] table的数组
  • 首先调用key1所在类的hashCode()方法计算出key1的哈希值,经过一系列的算法之后得到在数组中的存放位置,如果位置是空则添加成功
  • 如果不为空,意味着此位置存在一个或者多个数据(链表形式存储),那key1的哈希值与这些数据的哈希值进行比较:
    • 如果key1的哈希值与已存在的数据的哈希值不同则key1-value1添加成功
    • 若哈希值相同,调用key1所在类中equals方法:
      • 方法返回false,key1-value1添加成功
      • 方法返回true,value1覆盖value2的值

当然在不断的添加之后,会启动动态扩容机制,扩容于原来的两倍,并复制原来的数组到新数组中

JDK1.8之后 数组+链表,容量大于8使用红黑树

  • 创建HashMap对象的时候,底层没有创建一个长度为16的数组,而是在调用put()的方法才会创建长度为16的数组

  • 底层的数组是Node[] 不是Entry[]

  • 链表的长度大于8时将采用链表转换为红黑树进行存储数据

    扫描二维码关注公众号,回复: 11931645 查看本文章

    形成链表时,1.8以前新的数据指向旧的数据,1.8以后是旧的元素指向新的元素

HashMap 和 Hashtable的异同?
  • 线程安全方面:前者不安全,后者安全
  • 键值是否为null:前者可以为null,后者不可以为null

LinkedHashMap

LinkedHashMap主要继承HashMap用法上基本一样,主要区别就是LinkedHashMap内部提供了Entry,替换HashMap中的Node.

HashMap中的内部类

static class Node<K,V> implements Map.Entry<K,V> {
    
    
        final int hash;
        final K key;
        V value;
        Node<K,V> next;

LinkedHashMap的内部类

static class Entry<K,V> extends HashMap.Node<K,V> {
    
    
        Entry<K,V> before, after;
        Entry(int hash, K key, V value, Node<K,V> next) {
    
    
            super(hash, key, value, next);
        }
    }

TreeMap

元素可以根据键进行排序,元素具唯一性
排序方式(基本与TreeSet相同):
自然排序:让元素所在的类实现自然排序接口Comparable
比较器排序:让集合的构造方法接收一个比较器接口(Comparator的实现类对象)

猜你喜欢

转载自blog.csdn.net/qq_41857955/article/details/107436009
今日推荐