目录
参考:Java集合框架最全详解(看这篇就够了)
Java容器
1、Java集合框架体系图
Java集合类主要由两个根接口Collection和Map派生出来的。
2、Collection
Collection是单列集合,派生出List、Set、Queue
(1)List
List的实现类:
- **ArrayList:**有序、可重复
a.是一个动态数组object[10](初始容量10),可以插入任何符合规则的元素以及null,查询快
b.当数组元素到达一半时,会进行扩容为原来的1.5倍。因此当明确元素有多少时,可以指定初始容量值,避免多次扩容浪费时间和效率
c.线程不安全,效率高
d.ArrayList擅长于随机访问,同时ArrayList是非同步的。 - LinkedList
a.采用双向循环链表实现(Node{first,last}),实现了List和Deque接口,可以作为双端队列使用(可以做栈,也可以做队列)。插入、删除效率高
b.线程不安全,效率高 - Vector
a.动态数组object[10],查询快
b.当数组元素满了之后,扩容为原来的2倍
c.线程安全,效率低
d.与ArrayList相似,但是Vector是同步的,它的操作与ArrayList几乎一样
获取线程安全的List
(1)Vector:同步,效率低,开销大
(2)Collections.synchronizedList(list)
(3)JUC包下的CopyOnWriteArrayList<>()
读写分离:写操作在一个复制的数组中进行,读操作在原数组进行,互不影响
写时复制:写操作加锁,防止并发写入导致写入的数据丢失。写操作结束后,将原始数组执行复制数组
List<String> list=new CopyOnWriteArrayList<>();
(2)Set-
Set的实现类:
- HashSet: 无序、元素不可重复
a.底层实现是HashMap,可以存储null,查找快
b.底层数据结构是数组+链表 + 红黑树
c.线程不安全
d.通过equals和HashCode来判断两个元素是否相等 - LinkedHashSet: 有序(添加顺序)、元素不可重复
a.继承HashSet,本质是LinkedHashMap实现.可以存null
b.底层数据结构由哈希表(是一个元素为链表的数组)和双向链表组成
c.有序的, 根据HashCode的值来决定元素的存储位置,同时使用一个链表来维护元素的插入顺序
d.线程不安全
e.添加元素是类对象时,要求类重写hashcode和equals - TreeSet: 有序(自然排序)、元素不可重复
a.实现了SortedSet接口,底层是用TreeMap实现的.正常情况下不能有null值,可以重写Comparable接口 局可以有null值了。
b.本质上是一个红黑树
c.排序:自然排序(存储元素实现Comparable接口)和定制排序(创建TreeSet时,传递一个自己实现的Comparator对象,按照指定属性排序)
(3)Queue-队列集合
队列特点:FIFO(先进先出),尾部添加,头部删除
- Deque双端队列
a.Deque接口是Queue接口的子接口
b.当程序中需要使用“栈”这种数据结构时,推荐使用ArrayDeque。
- PriorityQueue
a.保存队列元素的顺序并不是按照加入的顺序,而是按照队列元素的大小进行排序的
b.允许插入null元素
3.Map
Map是双列集合,存储key-value键值对(key不能重复)。可以根据key访问value元素
Map派生出HashMap 、LinkedHashMap、TreeMap、HashTable、Properties
(1)HashMap
- 数据结构是数组+链表+红黑树(JDK8),根据hashCode存储数据,访问速度快,无序.
- 扩容:有索引的链表长度大于8且数组长度大于64时,转为红黑树
- 线程不安全,效率高。可以用 Collections的synchronizedMap方法使HashMap具有线程安全的能力**(效率低)**,或者使用ConcurrentHashMap类。
- 最多允许一个key为null,允许多个value为null
HashMap map=new HashMap();JDK8在底层没有创建长度为16的Node[],而是在首次调用put时,创建容量为16的数组
HashMap为啥线程不安全
(1)两个线程同时put(),且数组下标意义,那么可能导致前一个线程插入的值被后边的覆盖
(2)扩容导致死循环(头插法),将原本的顺序做了反转,导致死循环
(2)LinkedHashMap
- 继承自HashMap,维护着一个双重链接列表,此链接列表定义了迭代顺序,该迭代顺序可以是插入顺序或者是访问顺序。
(3)TreeMap
- 实现SortMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序(自然顺序),也可以指定排序的比较器(定制排序),当用Iterator遍历TreeMap时,得到的记录是排过序的
(4)HashTable
- 继承自Dictionary类
- 是线程安全的
- 另外Hashtable不允许key和value为null,并发性不如ConcurrentHashMap。
- 扩容为原来的2倍+1
(5)Properties
- 用来处理配置文件,key-value都是string类型
4.遍历Collection
(1)使用Iterator
public class CollectionDdemo {
public static void main(String[] args) {
Collection collection=new ArrayList();
collection.add('a');
collection.add('b');
Iterator iterator=collection.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
(2)使用foreach
public class CollectionDdemo {
public static void main(String[] args) {
Collection collection=new ArrayList();
collection.add('a');
collection.add('b');
//增强for循环
for(Object item:collection){
System.out.println(item);
}
}
}
5.遍历Map
(1)遍历key
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class Map1 {
public static void main(String[] args) {
Map<String,String> map=new HashMap<>();
map.put("name","Join");
map.put("age","18");
Set set=map.keySet();
Iterator iterator=set.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
(2)遍历value
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class Map2 {
public static void main(String[] args) {
Map<String,String> map=new HashMap<>();
map.put("name","Join");
map.put("age","18");
Collection<String> collection=map.values();
//迭代器
Iterator iterator=collection.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
//foreach
for (String item:collection
) {
System.out.println(item);
}
}
}
(3)遍历所有键值对
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class Map3 {
public static void main(String[] args) {
Map<String,String> map=new HashMap<>();
map.put("name","Join");
map.put("age","18");
//迭代器
Set<String> set1=map.keySet();
Iterator<String> iterator=set1.iterator();
while (iterator.hasNext()){
String key=iterator.next();
String value=map.get(key);
System.out.println(key+"->"+value);
}
//for循环
Set set=map.entrySet();
for(Object obj:set){
Map.Entry entry=(Map.Entry)obj;
System.out.println(entry.getKey()+"->"+entry.getValue());
}
}
}