面试官:请你说一下对集合的理解
思路:顺序清晰,根据所学顺序依次讲解,分为list,set和map。
步骤:
1. 集合底层
2. 集合实现原理
3. 集合之间的区别
4. 你对集合的见解(加分项)
5. 在开发中怎么使用集合的
示例:
ArrayList
- 首先list和set接口是继承了collection接口,list是有序的,其中每一个元素都有一个索引,第一个元素的索引是0,然后依次+1,set接口是无序.
ArrayList是一个动态数组,它允许任何符合规则的元素插入,甚至是null,在jdk1.7之后,ArrayList的初始容量是10,它是以1.5倍的大小进行扩容的,他的增删操作的时间复杂度是n,但是它的随机查询的时间复杂度是1,所以他的查询效率是最高的.
LinkedList
- LinkedList他的底层是一个双向链表,所以他的增删操作的时间复杂度是1,但是它随机访问的时间复杂度是n,但是它的空间复杂度比ArrayList要高,因为它的空间是离散的,而反映在我们在项目中,更多的是查询某个条件,所以这就是为什么我们平时一般使用ArrayList,而相对较少使用LinkedList,但是他也有ArrayList做不到的事情,例如LinkedList可以模拟栈和队列的逻辑.
Vector
- Vector它底层与ArrayList相似,但是它多了一个锁,所以它是线程安全的,但是线程安全必然会导致他的效率偏低,可是jdk1.7之后,它的底层实际上被优化了,但是我们基本不用她,可能是因为我们用ArrayList用习惯了,但是我觉的,如果你非要保证数据安全,而且还必须使用list集合,如果你去使用ArrayList,那么就必须要认为手动的给它加锁,这样反而会导致执行效率比vector低,这时候就推荐使用vector,
Stack
- Stack是一个栈,他继承了Vector,但是我们实际开发中,就算使用到了栈的逻辑,大部分还是使用linkedList.因为我们在使用栈逻辑的时候,更多的是出栈和入栈,linkedlist的效率比他高.
HashSet
- Set接口也是继承了collection接口, 但是它的实现类hashset和treeset还是有很大的不同点的,
首先hashset,它的底层实际上用到的是hashmap中的键值,它是根据hashcode的值来决定元素所在的位置的,它是可以放null值的,但是只能放一个,因为它是去重的,它的去重原理是很具hashcode方法和equals方法来决定的,这里有个细节,它的顺序不是永远都那样,如果你第二次存值,可能顺序是不一样的.
TreeSet
- treeset它的底层是treemap,它是可以被排序的,我们可以实现comparable接口来自然排序,也可以继承comparter抽象类来排序.
LinkedHashSet
- Linkedhashset,虽然是他也是根据hashcode来决定元素的位置,但是他还有一个链表来存储元素的次序,所以,在遍历的时候linkedhashset的效率是比hashset要高的,但是插入操作还是没hashset高.
HashMap - map接口,它是由一组键值对的形式组成的集合,在map中保证了key与value之间的对象关系,也就是说,一个key只能对应一个value,所以它是不能存储相同的key值,但是value是可以有重复的,
hashmap它的底层是位桶加链表的来实现的,默认情况下,它首先创建了一个长度为16
的数组,当加载因子超过了4分支三的话,就会进行2倍扩容,我们纵向来看,如果算出hashcode的值是一样的,就会纵向以解决冲突的拉链法来创建一个链表,但是经过jdk1.8之后,如果这个链表,它的长度超过8个了,就会变为红黑树,
TreeMap
- treemap它的底层就只有一个红黑树,而不是平衡二叉树,因为,你要是平衡二叉树,那么你就要不听的旋转来实现平衡二叉树的规则,这个操作是需要时间的,如果多了,必然会导致性能的地下,虽然平衡二叉树的他的最小时间复杂度较低,但是总和考虑还是红黑树更好一点,treemap是不允许键值为null的.
HashTable
- hashtable:它底层和hashmap是一样的,但是他是线程安全的.