Java 集合笔记
1. 集合的常用实现类
接口 | 常用实现类 | 底层结构 | 特点 |
---|---|---|---|
List | ArrayList | 动态数组 | 随机访问快,增删中间慢 |
List | LinkedList | 双向链表 | 增删头尾快,随机访问慢 |
Set | HashSet | 哈希表 | 去重,无序 |
Set | TreeSet | 红黑树 | 去重,自动排序(升序或自定义) |
Map | HashMap | 哈希表 | 键唯一,无序 |
Map | TreeMap | 红黑树 | 键唯一,自动排序 |
1.1 线程安全问题
非线程安全的集合:ArrayList、HashMap、HashSet ,多个线程同时调用它们的方法(add/remove/get),不额外加锁就可能抛出异常(如ConcurrentModificationException)或产生脏数据。
想要线程安全,可以用 Collections.synchronizedList(new ArrayList<>())。直接用 CopyOnWriteArrayList、ConcurrentHashMap 等并发集合。这些类内部已经用锁、CAS 或其他并发算法保证了多线程同时操作也安全。如:
// 多个线程随便 add/remove/get,不会出错
List<Integer> safeList = new CopyOnWriteArrayList<>();
1.2 简单归纳
集合类型 | 线程安全? | 备注 |
---|---|---|
ArrayList | × | 需额外加锁 |
HashMap | × | 需额外加锁 |
Vector / Hashtable | √ | 早期同步类,性能差 |
Collections.synchronizedXxx | √ | 包装后安全,但锁粒度大 |
CopyOnWriteArrayList | √ | 读多写少场景 |
ConcurrentHashMap | √ | 高并发场景首选 |
2. 常见操作方法
2.1 List 操作
List<String> list = new ArrayList<>();list.add("A"); // 追加
list.add(1, "B"); // 指定位置插入
list.set(0, "X"); // 替换
String e = list.get(2); // 按索引取值
int n = list.size(); // 元素个数
list.remove("A"); // 按对象删
list.remove(2); // 按索引删
boolean has = list.contains("X");
list.sort(String.CASE_INSENSITIVE_ORDER); // 排序
2.2 Set 操作
Set<Integer> set = new HashSet<>();set.add(10); // 添加
set.remove(10); // 删除
boolean exists = set.contains(10);
int s = set.size();
for (Integer i : set) { } // 遍历
2.3 Map 操作
Map<String, Integer> map = new HashMap<>();map.put("apple", 3); // 存键值
map.putIfAbsent("pear", 1); // 不存在才放
int v = map.get("apple"); // 按键取值
map.remove("apple");
boolean hasKey = map.containsKey("apple");
for (Map.Entry<String,Integer> e : map.entrySet()) {System.out.println(e.getKey() + " -> " + e.getValue());
}
3. 注意事项
- 用 equals() 比较内容,而非 ==
- 遍历过程中删除元素用 Iterator.remove() 或 removeIf(),避免 ConcurrentModificationException。
- 想保持插入顺序的 Set,用 LinkedHashSet;想按访问顺序做缓存淘汰,用 LinkedHashMap 开启 access-order。
- 需要线程安全时,优先选 java.util.concurrent 包里的类,而不是 Collections.synchronizedXxx。
- 要顺序用 List,要去重用 Set,要键值对用 Map。
- 读多写少用 ArrayList,写多读少用 LinkedList。
- 需要并发用 concurrent,需要排序用 Tree。