首先要说一下,本文对这些Java集合框架的面试题只作了一个总结式的回答,对每一道题目,都值得深刻去了解一下(什么是扎实基本功,这些就是基本功~~),后续可能对每一道题目拆开独立篇章来深刻讲解一下。html
你们看到这些总结,有疑惑的,就赶忙去查一查深刻了解一下,固然也欢迎指出文中错误之处。java
如下是大纲:面试
HashMap和HashTable的区别?算法
说一下 HashMap 的底层结构?数组
为何HashMap是线程不安全的安全
ArrayList 和 LinkedList 的区别是什么?数据结构
ArrayList 和 Vector 的区别是什么?框架
Array 和 ArrayList 有何区别?函数
说一下 HashSet 的实现原理?性能
如何决定使用 HashMap 仍是 TreeMap?
List、Set、Map 之间的区别是什么?
HashMap怎样解决hash冲突
HashMap 不是线程安全的
HashMap 是 map 接口的实现类,是将键映射到值的对象,其中键和值都是对象,而且不能包含重复键,但能够包含重复值。HashMap 容许 null key 和 null value,而 HashTable 不容许。
HashTable 是线程安全 Collection。
HashMap 是 HashTable 的轻量级实现,他们都完成了Map 接口,主要区别在于 HashMap 容许 null key 和 null value,因为非线程安全,效率上可能高于 Hashtable。
区别:
HashMap容许将 null 做为一个 entry 的 key 或者 value,而 Hashtable 不容许。
HashMap 把 Hashtable 的 contains 方法去掉了,改为 containsValue 和 containsKey。由于 contains 方法容易让人引发误解。
HashTable 继承自 Dictionary 类,而 HashMap 是 Java1.2 引进的 Map interface 的一个实现。
HashTable 的方法是 Synchronize 的,而 HashMap 不是,在多个线程访问 Hashtable 时,不须要本身为它的方法实现同步,而 HashMap 就必须为之提供外同步。
HashMap的主干是一个Entry数组。Entry是HashMap的基本组成单元,每个Entry包含一个key-value键值对。总体结构图:
HashMap由数组+链表组成的。
数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的,若是定位到的数组位置不含链表(当前entry的next指向null),那么对于查找,添加等操做很快,仅需一次寻址便可;若是定位到的数组包含链表,对于添加操做,其时间复杂度为O(n),首先遍历链表,存在即覆盖,不然新增;对于查找操做来说,仍需遍历链表,而后经过key对象的equals方法逐一比对查找。因此,性能考虑,HashMap中的链表出现越少,性能才会越好。
见20期:【20期】你知道为何HashMap是线程不安全的吗?
ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
对于随机访问get和set,ArrayList以为优于LinkedList,由于LinkedList要移动指针。
对于新增和删除操做add和remove,LinedList比较占优点,由于ArrayList要移动数据。
1.同步性:
Vector是线程安全的,也就是说是它的方法之间是线程同步的,而ArrayList是线程序不安全的,它的方法之间是线程不一样步的。若是只有一个线程会访问到集合,那最好是使用ArrayList,由于它不考虑线程安全,效率会高些;若是有多个线程会访问到集合,那最好是使用Vector,由于不须要咱们本身再去考虑和编写线程安全的代码。
PS:对于Vector&ArrayList、Hashtable&HashMap,要记住线程安全的问题,记住Vector与Hashtable是旧的,是java一诞生就提供了的,它们是线程安全的,ArrayList与HashMap是java2时才提供的,它们是线程不安全的。因此,咱们讲课时先讲老的。
2.数据增加:
ArrayList与Vector都有一个初始的容量大小,当存储进它们里面的元素的个数超过了容量时,就须要增长ArrayList与Vector的存储空间,每次要增长存储空间时,不是只增长一个存储单元,而是增长多个存储单元,每次增长的存储单元的个数在内存空间利用与程序效率之间要取得必定的平衡。
Vector默认增加为原来两倍,而ArrayList的增加策略在文档中没有明确规定(从源代码看到的是增加为原来的1.5倍)。ArrayList与Vector均可以设置初始的空间大小,Vector还能够设置增加的空间大小,而ArrayList没有提供设置增加空间的方法。
即Vector增加原来的一倍,ArrayList增长原来的0.5倍。
Array 能够包含基本数据类型和引用类型,ArrayList只能包含引用类型。
ArrayList是基于数组实现的,Array大小不能够调整大小,但ArrayList能够经过内部方法自动调整容量。
ArrayList是List接口的实现类,相比Array支持更多的方法和特性。
1.HashSet是基于HashMap实现的,默认构造函数是构建一个初始容量为16,负载因子为0.75 的HashMap。封装了一个 HashMap 对象来存储全部的集合元素,全部放入 HashSet 中的集合元素实际上由 HashMap 的 key 来保存,而 HashMap 的 value 则存储了一个 PRESENT,它是一个静态的 Object 对象。
2.当咱们试图把某个类的对象当成 HashMap的 key,或试图将这个类的对象放入 HashSet 中保存时,重写该类的equals(Object obj)方法和 hashCode() 方法很重要,并且这两个方法的返回值必须保持一致:当该类的两个的 hashCode() 返回值相同时,它们经过 equals() 方法比较也应该返回 true。一般来讲,全部参与计算 hashCode() 返回值的关键属性,都应该用于做为 equals() 比较的标准。
3.HashSet的其余操做都是基于HashMap的。
见03期:【03期】如何决定使用 HashMap 仍是 TreeMap?
List(列表)
List的元素以线性方式存储,能够存放重复对象,List主要有如下两个实现类:
1.ArrayList: 长度可变的数组,能够对元素进行随机的访问,向ArrayList中插入与删除元素的速度慢。JDK8中ArrayList扩容的实现是经过grow()
方法里使用语句newCapacity = oldCapacity + (oldCapacity >> 1)
(即1.5倍扩容)计算容量,而后调用Arrays.copyof()
方法进行对原数组进行复制。
LinkedList: 采用链表数据结构,插入和删除速度快,但访问速度慢。
Set(集合)
Set中的对象不按特定(HashCode)的方式排序,而且没有重复对象,Set主要有如下两个实现类:
1.HashSet:HashSet按照哈希算法来存取集合中的对象,存取速度比较快。当HashSet中的元素个数超过数组大小*loadFactor(默认值为0.75)时,就会进行近似两倍扩容(newCapacity = (oldCapacity << 1) + 1
)。
2.TreeSet:TreeSet实现了SortedSet接口,可以对集合中的对象进行排序。
Map(映射)
Map是一种把键对象和值对象映射的集合,它的每个元素都包含一个键对象和值对象。Map主要有如下实现类:
HashMap:HashMap基于散列表实现,其插入和查询<K,V>
的开销是固定的,能够经过构造器设置容量和负载因子来调整容器的性能。
LinkedHashMap:相似于HashMap,可是迭代遍历它时,取得<K,V>
的顺序是其插入次序,或者是最近最少使用(LRU)的次序。
TreeMap:TreeMap基于红黑树实现。查看<K,V>
时,它们会被排序。TreeMap是惟一的带有subMap()
方法的Map,subMap()
能够返回一个子树。
见16期:【16期】你能谈谈HashMap怎样解决hash冲突吗
原文出处:https://www.cnblogs.com/javazhiyin/p/11981387.html