Java高级编程之双列集合

双列集合

常见双列集合体系如下图:

  • Map接口

  • 存储Key-Value对的双列数据;

    • HashMap
      作为Map接口的主要实现类,线程不安全,但效率高;可以存储null的key和value;
      底层实现:JDK7及以前(数组+链表);JDK8(数组+链表+红黑树)
      • LinkedHashMap
        HashMap子类,可以按照添加元素顺序遍历该集合元素,因为:其在原有的HashMap底层上添加以一对引用,指向前一 个和后一个元素,当有频繁的遍历操作时,使用此集合效率高
    • Hashtable
      作为古老的实现类,线程安全但效率低;不能存储null的key和value
      • Properties
        常用来处理配置文件,key和value都为Sring类型;
        存取数据时,一般用setProperty(String key,String value)和getProperty(String key)方法
    • SortedMap接口(少用)
    • TreeMap
      保证按照添加的key-value对进行排序,实现排序遍历;其底层使用的是红黑树;
  • Map结构的理解:
    Map的key:无序不可重复,使用Set存储所有的key【key所在的类要重写hashCode和equals方法】
    Map的value:无序可重复,使用Collection存储所有的value【value所在的类要重写equal方法】
    一个键值对:无序不可重复,一个key-value构成了一个Entry对象;
    Map中的entry:无序不可重复的,使用Set存储所有的entry;

  • Map中定义的方法:
    添加、删除、修改操作:
    Object put(Object key,Object value):将指定key-value添加到(或修改)当前Map对象中;
    void putAll(Map m):将m中的所有key-value对存放到当前map中;
    Object remove(Object key):移除指定key的key-value对,并返回value;
    void clear():清空当前Map中的所有数据
    元素查询的操作:
    Object get(Object key):获取指定key对应的value;
    boolean containsKey(Object key):是否包含指定的key;
    boolean containsValue(Object value):是否包含指定的value;
    int size():返回map中key-value对的个数;
    boolean isEmpty():判断当前map是否为空;
    boolean equals(Object obj):判断当前map和参数对象obj是否相等;
    元视图操作的方法:
    Set keySet():返回所有key构成的Set集合;
    Collection values():返回所有value构成的Collection集合;
    Set entrySet():返回所有key-value对构成的Set集合;
    常用方法:
    添加:put(Object key,Object value)
    删除:remove(Object key)
    修改:put(Object key,Object value)
    查询:get(Object key)
    长度:size()
    遍历:keySet() / values() / entrySet()

  • HashMap的底层(JDK7为例):

    • 源码中重要标识符及其值
      DEFAULT_INITAL_CAPACITY:HashMap的默认初始容量(16)
      DEFAULT_LOAD_FACTOR:默认的加载因子(0.75)
      threshold:扩容临界值=默认初始容量加载因子(160.75=12)
      TREEIFY_THRESHOLD:Bucket(桶)中链表长度大于该默认值(8),则转化为红黑树
      MIN_TREEIFY_CAPACITY:Bucket中Node被树化时最小的hash表(数组)容量(64)

    • 实现原理:
      HashMap map = new HashMap();
      在创建对象之后,HashMap会创建一个长度为16的数组【Entry table[]】;
      …可能已经多次put操作…
      put(key1,value1);
      首先,调用key所在的类的hashCode方法计算出key的hash值,再通过某种算法计算出该key要存储的数 组索引:
      1)若该索引位置没有元素,则添加成功【情况1】;
      2)若该索引位置有一个或多个元素(链表形式存在),则分别比较这些元素的哈希值:
      |— 若与所有元素哈希值不同则添加成功【情况2】;
      |— 若与其中一个元素哈希值相同,则调用key所在类的equals方法,
      若返回false,则添加成功【情况 3】,若返回true,则用新的value1替换原来的value;

      声明一:关于【情况2】和【情况3】,新的key1-value1与原来的数据以链表形式存储;
      声明二:在不断添加过程中会涉及到扩容问题,当超出临界值【默认threshold】时,
      集合容量会扩大到原来两倍,并将原有的数据复制过来;

  • 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);
      }
    
  • JDK8 相较于JDK7在底层实现方面的不同:
    1)当new HashMap()时,底层没有创建一个长度为16的数组;
    2)JDK8中底层的数组是Node[],而不是Entry[]
    3)在第一次调用put方法时,才创建了一个长度为16的数组
    4)JDK7底层的数据结构【数组+链表】与JDK8中【数组+链表+红黑树】不同
    4.1) 形成链表时,七上八下(jdk7:新的元素指向旧的元素。jdk8:旧的元素指向新的元素)
    4.2)当数组的某一个索引位置上的元素以链表形式存在的数据个数 > 8 且当前数组的长度 > 64时,此时此索引位置上的所数据改为使用红黑树存储
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值