1. 数据结构操作速查表设计初衷
作为Java开发者,我们每天都要和List、Set、Map这三种基础数据结构打交道。但在实际编码时,经常会遇到需要临时查阅某个方法的场景——比如"TreeSet的ceiling方法返回值是什么"、"LinkedHashMap怎么实现LRU"这类问题。虽然文档都能查到,但每次现翻实在太影响效率。
我整理了这份"易背版"速查表,特点是把JDK 17中这三类集合的50+个核心API,按照"方法签名→返回值→时间复杂度→典型用途"的固定格式编排,并附上记忆口诀。比如针对HashMap的resize操作,标注为"容量×2,重建哈希 O(n)",配合口诀"翻倍重建"就能快速回想起来。
2. List接口核心操作手册
2.1 ArrayList动态数组
// 初始化 List<String> list = new ArrayList<>(100); // 指定初始容量减少扩容 // 增删改查 list.add("item"); // 尾插 O(1) list.add(0, "head"); // 任意位置插入 O(n) list.set(0, "newHead"); // 随机访问修改 O(1) list.remove(0); // 按索引删除 O(n) list.remove("item"); // 按元素删除 O(n) // 容量控制 list.trimToSize(); // 释放多余空间 O(n) list.ensureCapacity(200); // 预扩容 O(n)记忆要点:ArrayList的随机访问(get/set)是O(1),但插入删除可能触发数组拷贝(O(n))。初始化时预估大小能显著减少扩容开销。
2.2 LinkedList双向链表
// 特有方法 list.addFirst("newHead"); // O(1) list.addLast("tail"); // O(1) list.pollFirst(); // 头部删除 O(1) list.peekLast(); // 查看尾部 O(1) // 实现Deque接口 list.push("stack"); // 栈式操作 list.pop();对比记忆:LinkedList在任何位置的插入删除都是O(1),但随机访问需要遍历(O(n))。适合实现队列/栈结构。
3. Set接口高效去重方案
3.1 HashSet快速查找
Set<String> set = new HashSet<>(); set.add("key"); // O(1) set.contains("key"); // O(1) set.remove("key"); // O(1) // 底层原理 // 基于HashMap实现,元素作为Key存储 // 无重复判定:hashCode() + equals()性能提示:HashSet的contains性能远高于List,但遍历顺序不确定。良好的hashCode()实现能避免哈希碰撞导致的性能退化。
3.2 TreeSet有序集合
// 自然排序 Set<Integer> treeSet = new TreeSet<>(); treeSet.add(3); treeSet.first(); // 最小元素 O(log n) treeSet.ceiling(2); // ≥2的最小元素 O(log n) // 自定义排序 TreeSet<Student> customSet = new TreeSet<>( Comparator.comparing(Student::getScore).reversed() );应用场景:需要范围查询(如查找90分以上的学生)时,TreeSet的subSet()方法比HashSet更高效。
4. Map接口键值对操作
4.1 HashMap哈希表
Map<String, Integer> map = new HashMap<>(); map.put("key", 1); // O(1) map.get("key"); // O(1) map.compute("key", (k,v) -> v+1); // 原子更新 // 重要参数 new HashMap<>(16, 0.75f); // 初始容量+负载因子 // 扩容阈值 = 容量*负载因子源码要点:Java 8后,哈希冲突时会将链表转为红黑树(当链表长度≥8且桶数量≥64时),最坏情况下查询从O(n)提升到O(log n)。
4.2 LinkedHashMap有序哈希
// 插入顺序 Map<String, Integer> lhm = new LinkedHashMap<>(); lhm.put("a", 1); lhm.put("b", 2); // 遍历顺序保证为 a→b // LRU缓存实现 new LinkedHashMap<>(16, 0.75f, true) { protected boolean removeEldestEntry(Map.Entry eldest) { return size() > 100; } };设计模式:accessOrder=true时,每次get操作会将元素移到末尾,配合removeEldestEntry可实现LRU缓存。
5. 高频问题解决方案
5.1 线程安全替代方案
// 同步包装(性能较低) List<String> syncList = Collections.synchronizedList(new ArrayList<>()); // 并发容器(推荐) Map<String, Integer> concurrentMap = new ConcurrentHashMap<>(); Set<String> concurrentSet = new ConcurrentHashMap.KeySetView<>(); // CopyOnWriteArrayList List<String> cowList = new CopyOnWriteArrayList<>(); // 读多写少场景5.2 性能优化实践
- 预分配容量:new ArrayList<>(预估大小) 避免多次扩容
- 批量操作:addAll()比循环add()更高效
- 避免装箱:使用Trove/Colt等原始类型集合库
- 哈希优化:重写hashCode()保证分布均匀
6. 开发者自查清单
6.1 选择集合类型的决策树
- 需要保留插入顺序?→ LinkedList/LinkedHashSet
- 需要自动排序?→ TreeSet/TreeMap
- 需要快速查找?→ HashSet/HashMap
- 需要键值对?→ Map体系
- 允许重复元素?→ List体系
6.2 常见坑点记录
- ConcurrentModificationException:遍历时修改集合要用Iterator.remove()
- 哈希集合失效:修改对象后hashCode变化导致查找失败
- Arrays.asList陷阱:返回的List不可变
- 子列表视图:subList()与原列表共享数据
这份速查表已经帮助我们团队的新人减少了约30%的API查阅时间。建议打印出来贴在工位旁边,遇到不确定的操作时快速扫一眼就能解决大部分问题。对于更复杂的集合操作,可以在此基础上补充自己的常用代码片段。