HashTable、HashMap、TreeMap的区别

Map是集合框架的一部分(另一部分是Collection),以键值对的形式存储和操作数据的数据容器。

  • HashTable是Java早期基于Hash表的实现的类,本身就是同步,不论是key还是value都不支持null值,而且因为同步开销太大,现在基本不用这个容器了。
  • HashMap是也是基于Hash表实现的类,与HashTable的主要区别在于HashTable是线程安全的,而HashMap则是非线程安全的,key与value均可为null,但是只能有一个key为null;而且HashMap的put与get操作时间可以达到常数级,绝大部分利用键值对存取时就用HashMap。HashTable的默认容量为11,扩容时是原来的2倍加1,不要求底层数组为2的倍数,而HashMap默认容量为16,且容量要求为2的倍数,每次扩容2倍。
  • TreeMap是基于红黑树的一种可以顺序访问的Map,get、put、remove的操作时间复杂度是O(log(n))。如果TreeMap尚未实现Comparator接口时,key不可以为null。如果实现了Comparator接口时,如果对Null未进行判断,则key不可以为Null。

其中有两个是有序的,一个是LinkedHashMap,一个是TreeMap

LinkedHashMap一般是遍历顺序符合插入的顺序,底层是一个双向链表,LRU算法就可以用LinkedHashMap来实现。

TreeMap是利用红黑树来实现的,树的每个节点都会大于或等于它的左节点的值,并且小于等于右节点的值。实现了SortMap接口,可以根据key进行排序,默认为升序。 


HashMap底层是由数组和链表组成的复合结构,数组被分为一个个桶,通过Hash值来决定键值对在这个数组的地址,用拉链法来解决Hash冲突,在JDK1.8以后,加入了红黑树。当链表长度超过8的时候,就会树化,就会将链表改为红黑树。至于为什么会选择8这个数组,只要就是因为理想中,Hash表里的节点分布频率应该遵循泊松分布,按照泊松分布的计算公式计算出了桶元素个数与概率的对照表,发现当链表个数为8的时候概率非常的小。

有些人可能就会问红黑树查询效率那么高,为什么还要用单链表?

那是因为红黑树实现复杂得多,而且红黑树需要进行左右旋操作,而单链表不需要。

HashMap是按照了lazy-load,在使用的时候进行了初始化,如果表格是null,resize就会初始化它,如果容量不满足需求的时候会进行resize。具体键值对在Hash表的位置取决于位运算,(n-1)&Hash.

扩容后,需要将老的数组元素重新放入新的数组元素中,这是扩容的一个主要的开销来源。

HashMap的默认负载因子为0.75,一般不要去修改它,因为JDK的自身负载因子是根据通用场景来设计的,如果负载因子<0.75会导致更加频繁的扩容,增加了许多无用的开销,自身的访问性能会降低很多。如果负载因子>0.75会增加冲突,降低了HashMap的性能。

HashMap简单的来说就是 HashMap基于哈希表的思想,实现对数据的读写。当我们将键值对给put方法时,它会调用键的HashCode()方法来计算hashcode,然后通过找到桶的位置来储存该对象,如果我们想获取一个对象的时候,通过键的equals()方法来找到正确的键值对然后返回值对象。它使用了拉链法来解决Hash冲突,如果链表的大小超过了阈值(8),就会进行树化。

猜你喜欢

转载自blog.csdn.net/OrangeRawNorthland/article/details/83067408