HashMap和HashTable区别主要有以下几点:
1.线程的安全性。HashTable的大部分方法都使用了Synchronize同步锁,使得HashTable在多线程环境下变得安全,而HashMap则不是。
2.效率。HashTable因为加了同步锁导致效率变低。
3.存值。HashMap可以存储k-v,null-null,k-null,null-k(只能有一个k值为null),而HashTable只能存储k-v。
4.扩容方式。HashMap初始容量为16,扩容方式为2n,HashTable初始容量为11,扩容方式为2n+1。
ArrayList 和 LinkedList 的区别主要有以下几点:
1.底层数据结构不同。ArrayList底层为动态数组,LinkedList底层为双向链表。
2.针对场景不同。ArrayList适用于查询多,增删少的场景,LinkedList相反。
Collection下的子类都实现了这个iterator()方法,可以用对象直接调用。
它的特点主要有两个,1.使用Iterator遍历集合时,不允许对集合进行修改,否则抛出异常;2.使用Iterator 遍历集合时,可以用remove方法移除元素。
主要有以下几点:
1.ListIterator继承了Iterator 接口,额外添加了一些方法,比如添加一个元素,替换一个元素,获取前面或后面元素的索引。
2.Iterator 可以遍历List和Set两种集合,ListIterator 只能遍历List。
3.Iterator 只能单向遍历,ListIterator 可以双向遍历。
HashMap底层的数据结构是数组和链表/红黑树,其中每个元素都是链表,通过.put()和.get()进行存取值,
首先,当把key值传入时,会进行.hashcode()计算出key的哈希值,根据哈希值计算出对应的数组下标,然后将元素放入,这时会出现两种情况,第一种是数组的该位置没有存值,这时直接插入即可,第二种是出现哈希冲突,该位置有值,这时就要将传入的key和该位置的key值进行equals比较,比较的结果若相同,则将传入的value存入覆盖掉原先的值,比较的结果若不相同,则在该位置的链表上插入,1.7进行头插,1.8尾插;1.7会在插入前判断扩容,1.8会在插入后进行判断扩容;1.8会在链表大于8时将链表转化为红黑树。
用.get()取值时,先将传入的key计算哈希值,计算出对应的数组下标得到该key在数组中的位置,然后equals比较两key值是否相等,相等取出该value,不相等则取链表上后续元素的key进行比较,直到相等返回,或者没有相等的返回null。
1.table的容量由capacity参数确定,默认的初始容量是16,最大值为1<<30。
2.loadFactor代表负载因子,主要用于确定map扩容的阈值,比如,默认的初始容量为16,扩容阈值为12,当hashMap的实际存储元素数量size达到12时,进行扩容。
3.容量变化的方式为扩大为原来的两倍。
4.容量的变化会带来性能的影响,当性能要求比较高时,这种性能损失比较致命。
因为二叉树可能会出现特殊的情况,即二叉树形成线性结构,和链表结构一样,所以不能用二叉树。不能一直使用红黑树是因为引入红黑树是为了提高查找效率,当链表的长度大于8时,红黑树在自平衡时的性能消耗小于遍历链表的消耗,小于8时红黑树自平衡的消耗要大于遍历链表的消耗。
在扩容时,会先新建一个新容量为原来容量两倍的数组,并重新计算旧数组节点的存储位置,节点在新数组中的位置只有两种,原下标或者原下标+旧数组大小。
1.数据结构变了。1.7中数据结构为数组+链表,1.8为数组+链表+红黑树,当链表长度大于8时,会将链表转化为红黑树,小于6时,将红黑树转化成链表。
2.链表的插入方式变了。1.7中的插入方式为头插法,1.8为尾插法。
3.Entry被Node替代。
使用Collections的unmodifiableCollection方法将集合变为不可修改的。
java.util.concurrent并发包下的ConcurrentHashMap。同样的线程安全,ConcurrentHashMap1.7使用的是分段锁,1.8使用的是CAS(无锁算法)+ synchronized,HashTable使用的是Synchronized同步锁,前者将Map中的某个Segment(1.7)或者Node(1.8)锁住,后者将整个map锁住,效率上存在明显的差距。
1.粒度降低了;
2.JVM 开发团队没有放弃 synchronized,而且基于 JVM 的 synchronized 优化空间更大,更加自然。
3.在大量的数据操作下,对于 JVM 的内存压力,基于 API 的 ReentrantLock 会开销更多的内存。
程序运行时能够同时更新 ConccurentHashMap 且不产生锁竞争的最大线程数。默认为 16,且可以在构造函数中设置。当用户设置并发度时,ConcurrentHashMap 会使用大于等于该值的最小2幂指数作为实际并发度(假如用户设置并发度为17,实际并发度则为32)。
原文:https://www.cnblogs.com/thePeaceOftheLord/p/13741245.html