Java集合框架

守給你的承諾、 提交于 2020-12-16 06:56:30

一、ArrayList与LinkedList的异同

1、都不保证线程安全的

2、底层数据结构不同。ArrayList是数组,LinkedList是双向链表。

3、插入和删除的时间复杂度与元素位置有关。ArrayList在尾部增删时时间复杂度为O(1),在非尾部操作时时间复杂度为O(n-i)。LinkedList增删操作时时间复杂度为O(1)。

4、ArrayList支持快速随机访问(使用get(int index)方法),LinkedList不支持快速随机访问

5、内存空间占用方面。ArrayList造成的空间浪费体现在list列表结尾会预留一定的空间,而LinkList空间花费体现在每个元素要比ArrayList多消耗直接前驱和后驱的空间。

补充:RandomAccess接口

表示实现这个接口的类具有随机访问的功能

二、ArrayList与Vector的区别

1、ArrayList不是线程安全的,Vector所有的方法都是线程安全的。

2、二者的底层数据结构都是数组。当ArrayList空间不够时,默认增长50%,当Vector空间不够时,默认增长一倍。

3、Vector可以设置容量增加的参数,ArrayList不可以。

三、HashMap与HashTable的区别

1、HashMap不是线程安全的,HashTable是线程安全的。

2、效率。HashMap效率要高于HashTable

3、对Null key和Null Value的支持。HashMap支持Null key但只有一个,也支持Null value允许一个或多个;HashTable不支持Null key和Null value。

4、初始容量大小和扩容机制的不同。创建时不指定初始容量大小,HashMap默认初始值为16,之后每次扩容大小变为原来2倍(当元素总数超过Entry数组75%触发扩容机制);HashTable默认初始值为11,之后每次扩容为原来的2n+1。创建时制定初始容量大小,HashMap将其会扩容为2的幂次方大小(TablesizeFor方法保证),HashTable会直接使用给定的初始容量大小。

5、底层数据结构不同。JDK1.8之前HashMap的底层数据结构为数组链表(会出现多线程操作导致死循环问题),1.8之后为数组链表+红黑树,当链表超过阈值时(默认为8),变为红黑树,以减少搜索时间。

四、为什么HashMap的长度是2的幂次方?

因为hash值的取值范围比较大,内存无法存下,所以必须做取余运算。而只有当余数为2的幂次方时,才有hash%length==hash&(length-1)。之所以要使用&是因为&操作比%效率要高。所以HashMap的长度必须为2的幂次方。

五、HashMap与HashSet的区别

HashSet底层是基于HashMap实现的,除了clone、writeObject、readObject方法是HashSet自己实现外,其余的方法都直接调用HashMap的方法

五、ConcurrentHashMap与HashTable的区别

1、底层数据结构不同。ConcurrentHashMap在JDK1.7用的是分段数组+链表,JDK1.8用的是数组+链表/红黑树。HashTable用的是数组+链表。

2、线程安全。都是线性安全的,1,7ConcurrentHashMap用的是分段表实现线程安全,1.8用的是Node数组+链表+红黑树的数据结构,并发控制使用Synchronized和CAS来操作。HashTable使用synchronized来保证线程安全,效率十分低下。

六、说说List,Set,Map三者的区别?

List和Set实现了Collection接口,Map没有实现Collection接口,Map是一个接口。

List:1、允许有重复值。

         2、允许多个null值。

         3、是一个有序的容器,按输入顺序输出。

         4、常用实现类:ArrayList、LinkedList、Vector类,ArrayList最常用,可以随机访问元素,LinkedList用于频繁增删的情况。

Set:1、不允许有重复值。

         2、只允许有一个null值。

         3、无序容器,无法保证元素的存储顺序。TreeSet通过Comparable或Comparator维护一个排序顺序。

        4、常用实现类:HashSet、TreeSet、LinkedHashList。最常用的是基于HashMap实现的HashSet。

Map:1、Map的每个Entry都有两个对象都有一个键和一个值,键不允许有重复,值允许有多个重复值。

           2、Map的键只能有一个null,值可以有多个null。

           3、TreeMap通过Comparable或Comparator可以实现有序

           4、常用实现类:HashMap、LinkedHashMap、TreeMap、HashTable。

七、为什么HashMap会在多线程操作下可能出现死循环问题?

        在HashMap扩容时,要新建一个为原来长度两倍的数组,然后将原来的链表rehash(rehash的原因:扩容之后数组长度变了,hash的规则也变了)到新数组上,但java8之前用的是头插法,会改变链表的顺序,在多线程操作下就可能导致死循环。(java8采用尾插法解决了这个问题)

Java7在多线程操作HashMap时可能引起死循环,原因是扩容转移后前后链表顺序倒置,在转移过程中修改了原来链表中节点的引用关系。

Java8在同样的前提下并不会引起死循环,原因是扩容转移后前后链表顺序不变,保持之前节点的引用关系。

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!