List(可重复)
Set不可重复
- ArrayList(底层结构数组,线程不安全)
- LinkedList(链表,线程不安全)
- Vector(数组,线程安全)
ArrayList
arraycopy(),native,由C/C++来编写的
remove方法,移动后,最后一个元素设为null,让Gc回收
使用Arrays.copyOf(),copyOf中使用arraycopy()
ArrayList的add方法底层其实都是arraycopy()(由C/C++编写,native)
基于动态数组实现,在增删时,需要数组的拷贝复制。
默认初始化容量为10,每次扩容*1.5。
删除元素时不会减少容量(将后面置为null),希望减少容量调用trimToSize()。
线程不安全,能存null值。
Vector
jdk1.2的类
如果想要实现ArrayList同步,List list = Collections.synchronizedList(new ArrayList());
容量不够每次*2倍。
现已少用,被ArrayList替代(Vector所有方法都是同步有性能损失,扩容*2消耗更多内存)
LinkedList
底层双向链表
实现了Deque接口,可以像操作队列和栈一样。
get()和set(),根据下标判断从头遍历还是从尾遍历。
ArrayList和LinkedList的增删速度(总的来说增删多用LinkedList查询多用ArrayList):
使用add()增加到末尾,ArrayList快;
一直删除末尾元素ArrayList快(不用复制移动位置);
删除的是中间位置,ArrayList快。
Map集合、散列表、红黑树
transient:只修饰变量,被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。反序列化后类中static型变量username的值为当前JVM中对应static变量的值,这个值是JVM中的不是反序列化得出的。
Map
HashMap ConcurrentHashMap LinkedHashMap TreeMap (HashTable)
散列表
散列表用链表数组实现,每个列表称之为桶。
散列冲突
jdk1.8中,桶满时会从链表变为平衡二叉树,大于8转换为树小于6转换为链表,且键值对数量超过64才会发生转换。
如果散列表太满,是需要对散列表再散列,创建一个桶数更多的散列表,并将原有的元素插入到新表中,丢弃原来的表。
再散列:
- 装填因子(load factor)决定了何时对散列表再散列
- 装填因子默认为0.75,如果表中超过了75%的位置已经填入了元素,那么这个表就会用双倍的桶数自动进行再散列
红黑树
TreeSet TreeMap底层都是红黑树来实现的
常见各种树的用途:
AVL树:最早的平衡二叉树之一。windows对进程地址空间的管理用到了AVL树。
红黑树:平衡二叉树,广泛用在C++的STL中,如Map和set的实现。
B/B+树:磁盘文件组织、数据索引、数据库索引。
Trie树(字典树):用在统计和排序大量字符串,如自动机。
红黑树维持平衡的方式:
- 旋转:顺时针旋转和逆时针旋转
- 反色:交换红黑的颜色
- 这个两个实现比2-3树交换的节点(合并,分解)要方便一些
满足的约束条件:
- 红黑树是二叉搜索树。
- 根节点是黑色。
- 每个叶子节点都是黑色的空节点(NIL节点)。
- 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
- 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点(每一条树链上的黑色节点数量(称之为“黑高”)必须相等)。
https://blog.csdn.net/chen_zhang_yu/article/details/52415077
https://riteme.github.io/blog/2016-3-12/2-3-tree-and-red-black-tree.html#fn:red-is-left
http://www.sohu.com/a/201923614_466939
https://www.jianshu.com/p/37c845a5add6
https://www.cnblogs.com/nullzx/p/6111175.html
https://blog.csdn.net/fei33423/article/details/79132930
堆排序(看堆排序代码)完全二叉树有个特性:左边子节点位置 = 当前父节点的两倍 + 1,右边子节点位置 = 当前父节点的两倍 + 2
红黑树更详细的资料