集合是Java的基础,也是面试中必备的小菜,Java集合的底层原理,是我们需要必须掌握的。本文从多个维度来讲下Java场景的几种集合及面试考点。
1、List
1)ArrayList 数组结构,查询快,插入慢,复制的时候直接加一倍
2)LinkList 链表结构,查询慢,插入更新快。可以操作表头和表尾,可以当做堆栈,队列及双向队列使用
3)Vector 数组结构,支持同步,相当于加锁的ArrayList
2、Set
1)HashSet hash表结构
2)TreeSet
TreeSet是二叉树(红黑树的数据结构)实现的,自动排序,不允许放入null
3)LinkHashSet
LinkedHashSet底层是LinkHashMap。保证顺序,也就是说遍历序和插入序是一致的。
3、Map
1)HashTable
2)HashMap
- 2.1) hashmap1.7
2.1.1)基本结构:数组+链表,负载因子0.75,扩容双倍
2.1.2)负载因子为啥0.75:“哈希冲突”和“空间利用率”矛盾的一个折衷
2.1.3)扩容为啥是2^n:方便位运算,使得数据分布均匀
2.1.4)扩容死链:头插法,在多线程下会产生环形链表,查询的时候就会死循环
- 2.2) hashmap1.8
2.2.1)基本结构:数组+链表+红黑树
2.2.2)key必须实现Comparable接口或者在构造TreeMap传入自定义的Comparator
2.2.3)HashMap的线程不安全主要体现在下面两个方面:
1.在JDK1.7中,当并发执行扩容操作时会造成环形链和数据丢失的情况。
2.在JDK1.8中,在并发执行put操作时会发生数据覆盖的情况。
2.2.4)hashmap1.8 put过程
2.2.5)hashmap1.8 GET过程
首先计算hash,然后去数组中查询,是红黑树节点就去红黑树上查,是链表节点就去链表中查
2.2.6)链表->红黑树条件:链表长度大于8,数组长度大于64
2.2.7)为啥不直接使用红黑树:红黑树占用的空间比较大,所以只有节点数太多的时候才会使用红黑树
2.2.8)链表中的节点遵循泊松分布,而且根据统计,链表中节点数是8的概率已经接近千分之一,也就是大部分情况下,hashmap还是使用的链表
2.2.9)为什么到8转为红黑树 到6转为链表 :避免频繁来回转换
3) ConcurrentHashMap
3.1)1.7 分段锁,继承ReetrantLock
3.2)1.8 Synchronized(非空节点)+CAS(空节点)
3.3)1.8 put过程
3.4)1.8 get过程
get很简单,通过key计算hash,如果key hash相同就返回,如果是红黑树按照红黑树获取,都不是就遍历链表获取。
3.5)为啥放弃segment
1)锁力度变小,扩容后锁竞争更大,2)hash冲突,3)减小扩容力度
3.6)synchronized替换ReentranLock
1)减少内存开销2)synchronized是JVM直接支持,有加锁优化
3.5)红黑树对比平衡树
- 红黑树相比avl树,在检索的时候效率其实差不多,都是通过平衡来二分查找。但对于插入删除等操作效率提高很多。
- 红黑树不像avl树一样追求绝对的平衡,他允许局部很少的不完全平衡,这样对于效率影响不大,但省去了很多没有必要的调平衡操作,avl树调平衡有时候代价较大,所以效率不如红黑树。
反射
使用反射可以赋予jvm动态编译的能力,否则类的元数据信息只能用静态编译的方式实现,例如热加载,Tomcat的classloader等等都没法支持。
通过反射,java可以动态地加载未知的外部配置对象,临时生成字节码进行加载使用,从而使代码更灵活!可以极大地提高应用的扩展性!