集合
如果你有更好的想法请在评论区留下您的答案,一起交流讨论
- 
说说常见的集合有哪些? 答:主要分List、Set、Map、Queue四类,其中包含ArrayList、LinkedList、HashSet、TreeSet、HashMap 
- 
Comparable和Comparator接口的区别? 答:其两者的目的都是让对象可比。第一种将需要比较的类可实现Comparable并重写comparaTo方法制定比较规制,如此让类本身具备可比性,无需依赖其他第三方类。第二种为需要比较的类再定义一个比较类,该类需要基础Comparator接口实现compara方法传入俩个需要对象的进行比较,该方法需要依赖第三方类。 
- 
集合使用泛型有什么优点? 答:泛型允许我们为集合提供一个可以容纳的对象类型,因此,如果你添加其它类型的任何元素,它会在编译时报错。这避免了在运行时出现ClassCastException,因为你将会在编译时得到报错信息。 
- 
List、Set、Map之间的区别是什么? 答: 特性不同- List 有序可重复
- Set 无序不可重复
- Map KV形式存储,无序Key不可重复
 
- 
为什么Map接口不继承Collection接口? 答:Map提供的是键值对映射(即Key和value的映射),而collection提供的是一组数据(并不是键值对映射)。如果map继承了collection接口,那么所有实现了map接口的类到底是用map的键值对映射数据还是用collection的一组数据呢(就我们平常所用的hashMap、hashTable、treeMap等都是键值对,所以它继承collection完全没意义),而且map如果继承了collection接口的话还违反了面向对象的接口分离原则。 
- 
常用的线程安全的Map有哪些? 答:HashTable,ConcurrentHashMap 
- 
HashMap和Hashtable有什么区别? 答: - HashMap的Key和Value都可以为Null,而HashTable的Key和Value都不能
- HashMap的线程不安全效率高,HashTable的线程安全效率低
- HashMap继承的是AbstractMap,HashTable继承的是Dictionary接口
 
- 
HashMap和TreeMap怎么选? 答:存放的数据需要排序选择TreeMap,不需要排序选择HashMap,而且可以根据HashMap空间的使用,对初始容量和负载因子进行调优。 
- 
HashMap的数据结构是什么? 答:数组+链表/红黑树,一般称为“链表散列” 
- 
HashMap在JDK 8中有哪些改变? 答:JDK8之前HashMap采用的数据结构为数组+链表,JDK8之后HashMap采用数组+链表/红黑树。增加红黑树来优化链表过长时带来的查询性能消耗; 发生Hash冲突时 JDK7:插入链表的头部,头插法 
 JDK8:插入链表的尾部,尾插法
- 
HashMap是怎么解决Hash冲突的? 答: - 开放地址法:将散列算法算出来的hash通过位移操作符向后位移,使存放地址向后移位,如果还在冲突就继续移位
- 拉链发:在相同的散列位置处生产一个链表,链在冲突位置的后面
- 在Hash:重新计算Hash
- 建立公共溢出区
 
- 
HashMap是怎么扩容的? 答:当存储的数据量达到总容量的负载因子大小(默认0.75)时开始扩容。扩容会创建当前数组大小的两倍,再将原来的数据重新进行hash计算存储位置,由此可见HashMap扩容对性能的消耗比较严重 
- 
HashMap如何实现同步? 答: - Collections.synchronizedMap(HashMap对象)将HashMap转变为线程安全的
- HashMap进行写操作的步骤写在synchronized同步代码块中
- 用locklock.lock();Value = map.get(key);lock.unlock();
 
- 
ConcurrentHashMap的数据结构是什么? 答:CurrentHashMap的结构是Segment数组的意义就是将一个大的table分割成多个小的table来进行加锁,也就是上面的提到的锁分离技术,而每一个Segment元素存储的是HashEntry数组+链表,这个和HashMap的数据存储结构一样。 
- 
ArrayList是线程安全的吗? 答:线程不安全 
- 
常用线程安全的List集合有哪些? 答:Vector、以及通过java.util.Collections.SynchronizedList将任何List转换为线程安全、CopyOnWriteArrayList复制写入,添加元素时先加锁并且复制一份原来的List再添加元素,最后释放锁。 
- 
循环删除List集合可能会发生什么异常? 答:会导致数组元素位移,造成元素误删。解决办法是倒着删除或者使用迭代器遍历时删除 
- 
ArrayList和LinkedList有什么区别? 答:数据结构不同,ArrayList底层采用数组,查询快增加或删除慢(涉及到数据元素位移)。LinkedList底层采用链表结构,查询慢,增加删除快 
- 
ArrayList和Vector有什么区别? 答:ArrayList线程不安全效率高,Vector线程安全效率低 
- 
什么是CopyOnWriteArrayList? 答:CopyOnWriteArrayList是ArrayList的一个线程安全的变体,其中所有可变操作(add、set等等)都是通过对底层数组进行一次新的复制来实现的。相比较于ArrayList它的写操作要慢一些,因为它需要实例的快照。 CopyOnWriteArrayList中写操作需要大面积复制数组,所以性能肯定很差,但是读操作因为操作的对象和写操作不是同一个对象,读之间也不需要加锁,读和写之间的同步处理只是在写完后通过一个简单的"="将引用指向新的数组对象上来,这个几乎不需要时间, 
- 
什么是fail-safe? 答:当我们对集合结构上做出改变的时候,fail-fast机制就会抛出异常。但是,对于采用fail-safe机制来说,就不会抛出异常 这是因为,当集合的结构被改变的时候,fail-safe机制会在复制原集合的一份数据出来,然后在复制的那份数据遍历。 
- 
什么是fail-fast? 答:fail-fast的字面意思是“快速失败”。当我们在遍历集合元素的时候,经常会使用迭代器,但在迭代器遍历元素的过程中,如果集合的结构被改变的话,就会抛出异常,防止继续遍历。这就是所谓的快速失败机制。fail-fast,即快速失败机制,它是java集合中的一种错误检测机制,当多个线程(单个线程也是可以滴),在结构上对集合进行改变时,就有可能会产生fail-fast机制。 
- 
fail-fast和fail-safe有什么区别? 答: fail-safe机制fail-safe任何对集合结构的修改都会在一个复制的集合上进行修改,因此不会抛出ConcurrentModificationException fail-safe机制有两个问题 (1)需要复制集合,产生大量的无效对象,开销大 (2)无法保证读取的数据是目前原始数据结构中的数据。 fail-fast机制fail-fast机制在遍历一个集合时,当集合结构被修改,会抛出Concurrent Modification Exception。 fail-fast会在以下两种情况下抛出ConcurrentModificationException (1)单线程环境 集合被创建后,在遍历它的过程中修改了结构。 注意 remove()方法会让expectModcount和modcount 相等,所以是不会抛出这个异常。 (2)多线程环境 当一个线程在遍历这个集合,而另一个线程对这个集合的结构进行了修改。 
- 
HashSet的底层实现原理是什么? 答:HashSet底层依赖与HashMap进行数据存储,HashSet的元素就是HashMap中的Key,而Value则为Null 
- 
怎么确保一个集合不能被修改? 答:两种实现方式,Collections. unmodifiableCollection(Collection c) 方法创建的集合( 最终会返回一个由Collections.UnmodifiableCollection类,该类对所有的写操作都进行了重写覆盖,使其抛出UnsupportedOperationException异常),和使用Arrays.asList创建的集合(返回了一个Arrays的静态内部类ArrayList,原理与Collections.UnmodifiableCollection差不多)。