目录
1.引言
本文是对常见的java(1.8)集合的一些总结,不足之处,欢迎看官们在评论区纠正。
2.总结
^_^,先放大招
3.java集合概述
java集合框架图,摘自菜鸟教程:https://www.runoob.com/java/java-collections.html
3.1 ArrayList
最常用的集合之一。
底层数据结构为数组,数组的默认初始容量为10,当数据的大小大于10的时候,会进行自动扩容,新的容量为旧的容量的1.5倍。
ArrayList的元素可以存在重复,默认情况下元素的输入顺序与输出顺序一致。
可自定义元素比较器,修改元素输出顺序。
public static void main(String[] args) {
ArrayList<Integer> arrayList = new ArrayList<>();
arrayList.add(3);
arrayList.add(4);
arrayList.add(2);
arrayList.add(5);
arrayList.add(1);
arrayList.add(2);
System.out.println(arrayList); // [3, 4, 2, 5, 1, 2]
arrayList.sort((p, n) -> n - p);
System.out.println(arrayList); // [5, 4, 3, 2, 2, 1]
}
3.2 LinkedList
LinkedList类是双向链表,链表中的每个节点都包含了对前一个和后一个元素的引用。
与ArrayList类似,元素可以存在重复并且默认输出元素顺序和输入元素顺序一致。可自定义比较器用于实现元素输出顺序
LinkedList与ArrayList因为数据结构不同,所以在读写性能上也不一样,LinkedList适用于更多的写入与删除场景下,ArrayList则适用于读取较多的场景。
public static void main(String[] args) {
LinkedList<Integer> linkedList = new LinkedList<>();
linkedList.add(3);
linkedList.add(4);
linkedList.add(2);
linkedList.add(5);
linkedList.add(1);
linkedList.add(2);
System.out.println(linkedList); // [3, 4, 2, 5, 1, 2]
linkedList.sort((p, n) -> n - p);
System.out.println(linkedList); // [5, 4, 3, 2, 2, 1]
}
3.3 Vector
Vector继承AbstractList类,实现了List接口,因为在操作方法上都加上了同步锁,是一个相对线程安全的集合。
虽然Vector可以保证单个方法线程安全,但是对于复合操作的查询却并不能做到线程安全,需要调用方自己以Vector为锁来进行操作。
Vector可以再初始化的时候设置扩容参数capacityIncrement,如果在构造方法中设置了capacityIncrement > 0,那么新数组长度就是原数组长度 + capacityIncrement,否则新数组长度就是原数组长度 * 2。
与ArrayList类似,元素可以存在重复并且默认输出元素顺序和输入元素顺序一致。可自定义比较器用于实现元素输出顺序
public static void main(String[] args) {
Vector<Integer> vector = new Vector<>();
vector.add(3);
vector.add(4);
vector.add(2);
vector.add(5);
vector.add(1);
vector.add(2);
System.out.println(vector); // [3, 4, 2, 5, 1, 2]
vector.sort((p, n) -> n - p);
System.out.println(vector); // [5, 4, 3, 2, 2, 1]
}
3.4 HashMap
底层由 数组+链表+红黑树 实现,
HashMap的增加操作:根据key的hash值计算出一个值,该值当做数组的下标存入到数据。但是如果发现数组中该下标已经有值的存在(hash碰撞),那么旧值和新值则组合成链表存放于该下标上。链表长度超过8则进行判断,如果数组长度小于64那么进行扩容,否则就同一下标的链表转为红黑树。当HashMap进行resize的时候,发现某个数的元素小于等于6,那么会执行untreeify操作,把树再次转为链表。
HashMap内部由 Node<K,V> 数组保存数据,数据的下标是由key的hash得到,因此HashMap不支持自定义排序,并且输出顺序由 key 的hash值决定,所以输出元素的顺序和输入元素顺序无关,因此HashMap不是有序的。
public static void main(String[] args) {
HashMap<String, String> hashMap = new HashMap<>();
hashMap.put("1", "A");
hashMap.put("3", "A");
hashMap.put("2", "A");
hashMap.put("4", "A");
hashMap.put("3", "A");
System.out.println(hashMap); // {1=A, 2=A, 3=A, 4=A}
}
3.5 LinkedHashMap
LinkedHashMap 继承HashMap,是对HashMap的一层封装。LinkedHashMap可以认为是HashMap+LinkedList,即它既使用HashMap操作数据结构,又使用LinkedList维护插入元素的先后顺序
public static void main(String[] args) {
LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<>();
linkedHashMap.put("4", "A");
linkedHashMap.put("1", "A");
linkedHashMap.put("3", "A");
linkedHashMap.put("2", "A");
linkedHashMap.put("3", "A");
System.out.println(linkedHashMap); // {4=A, 1=A, 3=A, 2=A}
}
3.6 TreeMap
TreeMap的存储结构是红黑树,红黑树的节点之间是具备可比较性的,因此红黑树是有序的,他的元素输出顺序默认为从小到大,也可以自定义排序规则。
public static void main(String[] args) {
TreeMap<String, String> treeMap = new TreeMap<>(Comparator.reverseOrder());
treeMap.put("4", "A");
treeMap.put("1", "A");
treeMap.put("3", "A");
treeMap.put("2", "A");
treeMap.put("3", "A");
System.out.println(treeMap); // {4=A, 3=A, 2=A, 1=A}
}
3.7 Hashtable
HashTable内部由数组+链表实现。数组的下标同样由key的hash获取,和HashMap类似。
因此Hashtable不支持自定义排序,并且输出顺序由 key 的hash值决定,所以输出元素的顺序和输入元素顺序无关,因此Hashtable不是有序的。
public static void main(String[] args) {
Hashtable<String, String> hashtable = new Hashtable<>();
hashtable.put("4", "A");
hashtable.put("1", "A");
hashtable.put("3", "A");
hashtable.put("2", "A");
hashtable.put("3", "A");
System.out.println(hashtable); // {4=A, 3=A, 2=A, 1=A}
}
3.8 HashSet
HashSet的底层其实就是HashMap,它在内部维护了一个HashMap,key为HashMap的key,value为一个PERSENT(一个object对象)。
因此HashSet继承了HashMap的特性,值不能重复,不支持自定义排序,元素的输出顺序仅和hash有关,是个无序的集合。
public static void main(String[] args) {
HashSet<Integer> hashSet = new HashSet<>();
hashSet.add(5);
hashSet.add(3);
hashSet.add(4);
hashSet.add(2);
hashSet.add(5);
System.out.println(hashSet); // [2, 3, 4, 5]
}
3.9 LinkedHashSet
继承HashSet,底层也有HashMap实现,不同于HashSet, LinkedHashSet内部有一个Entry,用于维护元素的输出顺序。LinkedHashSet值不能重复,元素输出顺序和输入顺序一致,不支持自定义的比较器,是个有序的集合。
public static void main(String[] args) {
LinkedHashSet<Integer> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add(5);
linkedHashSet.add(3);
linkedHashSet.add(4);
linkedHashSet.add(2);
linkedHashSet.add(5);
System.out.println(linkedHashSet); // [5, 3, 4, 2]
}
3.10 TreeSet
TreeSet内部维护了一个TreeMap,key为TreeMap的key,value是一个PERSENT的object对象,因此TreeSet特性与TreeMap相当,可以自定义比较器,元素输出的顺序默认从小到大输出,是一个有序集合。
public static void main(String[] args) {
TreeSet<Integer> treeSet = new TreeSet<>((m,n)->n-m);
treeSet.add(5);
treeSet.add(3);
treeSet.add(4);
treeSet.add(2);
treeSet.add(5);
System.out.println(treeSet); // [5, 4, 3, 2]
}