3. JDK Map

JDK Map

Map接口中的方法

  1. 判断系。containsKey包含元素、containsValue包含值、isEmpty是否为空。
  2. 读取系。size大小、get获取元素
  3. 增删系。put增加、remove删除、putAll增加所有、clear清空。
  4. 转化系。entrySet返回键值对、、keySet返回键集合、values返回值集合。

Map下面的抽象类与接口

  1. AbstractMap AbstractMap中包含两个键值对类,SimpleImmutableEntrySimpleEntry前者初始化之后,不可修改值,后面不是。 简单实现了Map接口中的方法,
  2. ConcurrentMap ConcurrentMap中增加了两个替换replace、一个如果没有就设置putIfAbsent、一个移除键值remove四个方法。主要实现类为ConcurrentHashMap
  3. SortedMap SortedMap排序的Map,增加了头keyfirstKey,尾keylastKey,切片方法headMaptailMapsubMap、还有一个比较器comparator
  4. NavigableMap SortedMap子接口,新增一系列Navigable的方法,能访问有序Map中的第一个、最后一个、返回比入参大,入参小的等等,这里不细说。
  5. ConcurrentNavigableMap ConcurrentMap与NavigableMap的接合。

Map中的内部类

  1. Cellections中,SynchronizedSortedMapSynchronizedMapCheckedSortedMapCheckedMapEmptyMap。在JDK中集合的辅助类中已经说过。
  2. ConcurrentSkipListMap中的SubMapConcurrentSkipListMap的分段类
  3. TreeMap中的AscendingSubMapDescendingSubMap。分段类,升序与降序两种。

HashMap

内部原理

HashMap内部数据结果是数组+链表。 根据map的key的hash值,进行一系列的算法,最后模得数组中的下标,如果下标链表中有实体里,那就把这个元素放到链表的最前面。 数组大小是固定,所以需要动态扩容,是扩容却不是动态定内部数组大小,所以如果先放大,最后删除,但是数组大小不会缩小。 可以看到HashMapnull的key与value都有处理。

动态配置初始化大小

内部静态类Holder中可以配置初始化数组的大小jdk.map.althashing.threshold

modCount的作用

ArrayList一样,HashMap中也有modCount字段,同样的作用。

逃脱

因为是HashMap,所以元素放到map中的位置与对象的hash有关,所以在对象改变了hash值,就算对象引用没有变,也会每次放到不同的位置,换句话说,一个对象可以放在同一个map的不同位置。

public class Mappest {
    public int id;
    public String name;

    public Mappest(int id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public int hashCode() {
        return id + name.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if(!(obj instanceof Mappest)){
            return false;
        }
        Mappest m2 = (Mappest) obj;

        if(this.hashCode() == m2.hashCode()){
            return true;
        }
        return false;
    }

    public static void main(String[] args) {
        HashMap<Mappest, String> map = new HashMap<>();
        Mappest mada = new Mappest(1, "mada");
        map.put(mada, "1");

        mada.id = 2;
        map.put(mada, "2");

        for (Map.Entry en : map.entrySet()) {
            System.out.println(en.getValue());
        }
    }
}

HashTable

内部原理

HashMap的同步版本,synchronized同步方法。内部原理与HashMap类似。

TreeMap

内部原理

实现了NavigableMap接口。对外提供已排序的数组,内部使用的是红黑树结构(详细见这片文章)。 实例化TreeMap两种情况,一是Map元素实现java.lang.Comparable,二是java.util.Comparator比较器。

modCount

好吧,TreeMap中也有这个东东,作用类型。

AscendingSubMap与DescendingSubMap

AscendingSubMapDescendingSubMap表示升序,降序子Map。这里的升序是针对ComparableComparator而言,所以降序也只是反序ComparableComparator。 红黑树所有结点是有序存储。是升序,降序是对迭代顺序的。TreeMap是正序,所以在DescendingSubMap中,使用了Collections中的reverseOrder方法。

WeakHashMap

HashMap的WeakReference版本,WeakHashMap内部维护一个ReferenceQueue<Object>的数组,内部Entry继承WeakReference<Object>,通过WeakReference与ReferenceQueue配合实现了弱引用缓存,可以看这篇文章

LinkedHashMap

LinkedHashMap继承HashMap。内部使用HashMap储存数据,但是同时维持一个双向链表,用于记录访问顺序。 如果accessOrder为true。访问get方法,也会调整顺序:将被访问的元素,挪到顺序链表的表尾。

Properties

Properties继承Hashtable。用于读取properties文本。 借助XMLUtils读取xml文件。

EnumMap

枚举Map,Key只能是传入的枚举类实例。内部使用数组存储数据,而存取元素下标是枚举元素的ordinal,这样就没有下标计算过程,效率更高。

public V put(K key, V value) {
   typeCheck(key);

   int index = key.ordinal();
   Object oldValue = vals[index];
   vals[index] = maskNull(value);
   if (oldValue == null)
       size++;
   return unmaskNull(oldValue);
}

同样,也没有逃逸的问题。

IdentityHashMap

IdentityHashMap的内部结构与HashMap内部结构不同。

  1. 前者使用数组存储,后者使用数组+链表。
  2. 前者使用key相同(==),后者是相等(equal)。这样就不存在HashMap中逃脱的情节。
  3. 前者的下标如果存在实体,就会往下找一个有两个空的下标,将相同的两个实体都放入。

ConcurrentHashMap

ConcurrentHashMap内部将所有数据放到Segment数组中,而Segment中有HashEntry数组。所以是数组+数组格式。 Segment继承ReentrantLock,与HashTable不同,ConcurrentHashMap的锁对象不是整个Map,而是Segment

ConcurrentSkipListMap

TreeMap的同步版本。

转载于:https://my.oschina.net/markho/blog/808003

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值