前言
刚学完集合,脑瓜子嗡嗡的,写个博客整理一下。小白级理解,若有不当之处,敬请指出。
目录
正文
集合框架
如下图:边框为点线的是接口(如Collection),边框为折线的是抽象类(如AbstractList),边框为实线的为实现类(如Hashtable)。
List
元素可以重复,存储有序。
1.ArrayList
底层为数组。
由于下标的存在,使得它在随机查询某个元素的效率较高,但是在增删元素时,往往对应着该数据后的元素的后移或前移,这使得在多数据时它的修改效率较低。具体可参照下图。
另一个集合则和它相反。
2.LinkedList
底层为链表。
它没有下标标识每个数据,因此在做随机访问某个元素的效率会很低,因为它是从头开始查询的。但是链表中对数据做修改操作效率是很高的,它不需要对其他数据的位置产生影响,只需要在添加时将前后元素的指针指向需要操作的元素,在删除元素时将需要操作的元素的指针移走。下图可做参考。
Set
元素不可重复,存储无序。
1.HashSet
底层是数组+链表(哈希表、散列表)。
散列表是如何去重的?
散列表的大小默认为16,加载因子为0.75.
HashSet
的唯一性保证是依赖与hashCode()
和equals()
两个方法。
hashset add一个元素A的时候,首先获取这个元素的散列码(hashcode的方法),即获取元素的哈希值。
如果计算出的元素的存储位置目前没有任何元素存储,那么该元素可以直接存储在该位置上。
如果算出该元素的存储位置目前已经存在有其他元素了,那么会调用该元素的equals方法与该位置的元素再比较一次,如果equals返回的值是true,那么该元素与这个位置上的元素就视为重复元素,不允许添加,如果equals方法返回的是false,那么该元素运行添加。
2.TreeSet
底层是红黑树。
TreeSet
在保证元素唯一性的基础上,还可以对元素进行排序。
他和HashSet
不同的是不需要重写hashCode()
和equals()
方法,因为它去重是依靠比较器来去重,因为结构是红黑树,所以每次插入都会遍历比较来寻找节点插入位置,如果发现某个节点的值是一样的那就会直接覆盖。
Map
以键值对的形式存储数据,键不能重复,值可以重复。
1.HashMap
在JDK8以前,它的底层是数组+链表。JDK8及以后变成了数组+链表+红黑树。当hash表的单一链表长度超过 8 个的时候,链表结构就会转为红黑树结构。
为什么要这样设计呢?好处就是避免在最极端的情况下链表变得很长很长,在查询的时候,效率会非常慢。
所以其实HashMap的增删改查效率都很高。
增删改效率高是由于链表,查为什么效率也高呢————因为红黑树。
简单的说,红黑树是一种近似平衡的二叉查找树,其主要的优点就是“平衡“,即左右子树高度几乎一致,以此来防止树退化为链表,通过这种方式来保障查找的时间复杂度为 log(n)
下图为JDK8版本。
2.TreeMap
底层也是红黑树。
原理参考TreeSet。
3.HashTable
底层:哈希表。
HashMap是非同步的,没有对读写等操作进行锁保护,所以是线程不安全的,在多线程场景下会出现数据不一致的问题。而HashTable是同步的,所有的读写等操作都进行了锁(synchronized)保护,在多线程环境下没有安全问题。但是锁保护也是有代价的,会对读写的效率产生较大影响。