一页吃透三大核心接口的语义与差异
本页系统对比 List、Set、Map 的特性与典型实现,是集合框架面试的基础必备。
从语义到实现的完整理解:
深度解析:
// 语义差异的代码体现
public class CollectionSemantics {
public static void demonstrateListSemantics() {
List list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("Java"); // 允许重复
list.add(1, "Go"); // 按索引插入
System.out.println(list.get(0)); // 按索引访问
System.out.println("List 保持插入顺序: " + list);
}
public static void demonstrateSetSemantics() {
Set set = new HashSet<>();
set.add("Java");
set.add("Python");
set.add("Java"); // 自动去重
System.out.println("Set 自动去重: " + set);
System.out.println("快速查找: " + set.contains("Java"));
}
public static void demonstrateMapSemantics() {
Map map = new HashMap<>();
map.put("Java", 1);
map.put("Python", 2);
map.put("Java", 3); // 覆盖旧值
System.out.println("Map 键值映射: " + map);
System.out.println("通过 Key 获取: " + map.get("Java"));
}
} 从基础到高级的完整实现类体系:
// 各实现类的性能特征对比
public class ImplementationComparison {
// ArrayList - 最适合随机访问
public static void arrayListDemo() {
List arrayList = new ArrayList<>();
// 优点:get(index) O(1),内存连续,缓存友好
// 缺点:扩容时需要复制数组,中间插入删除 O(n)
arrayList.add("Element1");
arrayList.add("Element2");
String element = arrayList.get(0); // O(1) 访问
}
// LinkedList - 适合频繁插入删除
public static void linkedListDemo() {
List linkedList = new LinkedList<>();
// 优点:头尾插入删除 O(1),不需要预分配空间
// 缺点:随机访问 O(n),内存开销大,缓存不友好
linkedList.add("Element1");
((LinkedList) linkedList).addFirst("Element0"); // O(1)
}
// HashSet - 最快的去重和查找
public static void hashSetDemo() {
Set hashSet = new HashSet<>();
// 优点:add/contains/remove O(1),性能最佳
// 缺点:无序,不保证遍历顺序
hashSet.add("Java");
boolean exists = hashSet.contains("Java"); // O(1)
}
// LinkedHashMap - 保持顺序的高性能Set
public static void linkedHashSetDemo() {
Set linkedHashSet = new LinkedHashSet<>();
// 优点:保持插入顺序,性能接近 HashSet
// 缺点:内存开销略大于 HashSet
linkedHashSet.add("First");
linkedHashSet.add("Second");
// 遍历时按插入顺序输出
}
// HashMap - 最通用的映射结构
public static void hashMapDemo() {
Map hashMap = new HashMap<>();
// 优点:get/put O(1),支持 null key 和 value
// 缺点:非线程安全,无序
hashMap.put("key", "value");
Object value = hashMap.get("key"); // O(1)
}
// TreeMap - 有序映射
public static void treeMapDemo() {
Map treeMap = new TreeMap<>();
// 优点:按键排序,支持范围查询
// 缺点:性能 O(log n),需要实现 Comparable
treeMap.put("C", "Value3");
treeMap.put("A", "Value1");
treeMap.put("B", "Value2");
// 自动按 key 排序:A, B, C
}
// ConcurrentHashMap - 高并发映射
public static void concurrentHashMapDemo() {
Map concurrentMap = new ConcurrentHashMap<>();
// 优点:线程安全,高并发性能好
// 缺点:内存开销大,不支持 null key
concurrentMap.put("key", "value");
// 多线程环境下安全操作
}
} 选择策略:
典型场景:
List list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("A"); // 允许重复
System.out.println(list.get(0)); // A List list = List.of("A", "B", "C");
// 1. 传统 for
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
}
// 2. 增强 for(推荐)
for (String s : list) {
}
// 3. Iterator
for (Iterator it = list.iterator(); it.hasNext(); ) {
String s = it.next();
}
// 4. forEach + Lambda(推荐)
list.forEach(System.out::println);
// 5. Stream
list.stream().filter(s -> !s.isEmpty()).forEach(System.out::println); hashCode() 和 equals() 判断是否相同。compareTo() 或 Comparator 判断顺序与相等。equals 和 hashCode,去重会失效。Map map = new HashMap<>();
// 1. entrySet(推荐)
for (Map.Entry e : map.entrySet()) {
String k = e.getKey();
Integer v = e.getValue();
}
// 2. keySet
for (String k : map.keySet()) {
Integer v = map.get(k);
}
// 3. values
for (Integer v : map.values()) {
}
// 4. forEach(JDK 8+)
map.forEach((k, v) -> System.out.println(k + "=" + v)); 可以准备一两个例子:例如「订单 + 订单项」、「标签去重」、「按用户 ID 建索引」等。
Collections.synchronizedList / CopyOnWriteArrayList / ConcurrentHashMap 等并发实现。equals/hashCode。ConcurrentModificationException。核心考察点:接口设计、数据结构组合、性能优化、设计模式应用、泛型使用。
从需求分析到完整实现的统一容器设计:
// 统一容器:同时支持List和Set语义
class UnifiedCollection {
private List list = new ArrayList<>();
private Set set = new HashSet<>();
private Map indexMap = new HashMap<>();
public boolean add(T e) {
if (set.contains(e)) return false; // Set语义
list.add(e);
set.add(e);
indexMap.put(e, list.size() - 1);
return true;
}
public T get(int i) { return list.get(i); } // List语义
public boolean contains(Object o) { return set.contains(o); } // O(1)查找
public int fastIndexOf(Object o) { return indexMap.getOrDefault(o, -1); }
}
// 并发安全版本
class ConcurrentUnifiedCollection {
private List list = new ArrayList<>();
private Set set = new HashSet<>();
private ReadWriteLock lock = new ReentrantReadWriteLock();
public boolean addUnique(T e) {
lock.writeLock().lock();
try {
if (set.contains(e)) return false;
list.add(e); set.add(e);
return true;
} finally { lock.writeLock().unlock(); }
}
} 设计要点分析:
核心考察点:性能分析、策略模式、动态优化、数据结构特征、机器学习应用。
从性能监控到智能选择的完整解决方案:
// 智能集合选择器:根据使用模式自动优化
class SmartCollectionSelector {
private Collection collection = new ArrayList<>();
private int addCount, getCount, containsCount;
public boolean add(T e) {
addCount++;
boolean r = collection.add(e);
if (shouldOptimize()) optimize();
return r;
}
private boolean shouldOptimize() {
return (addCount + getCount + containsCount) % 100 == 0;
}
private void optimize() {
double accessRatio = (double) getCount / (getCount + containsCount + 1);
double modifyRatio = (double) addCount / (addCount + getCount + containsCount + 1);
Collection newColl;
if (accessRatio > 0.7) newColl = new ArrayList<>(); // 随机访问多
else if (modifyRatio > 0.6) newColl = new LinkedList<>(); // 修改多
else if (containsCount > getCount) newColl = new HashSet<>(); // 查找多
else return;
newColl.addAll(collection);
collection = newColl;
}
} 智能选择策略:
核心考察点:分布式系统设计、数据一致性、高可用架构、网络分区处理、性能优化。
从单机到分布式的集合框架设计:
// 分布式集合:一致性哈希 + 数据分片
class DistributedSet {
private ConsistentHash hash;
private Map> nodeData = new ConcurrentHashMap<>();
private String localNode;
public boolean add(T e) {
String node = hash.getNode(e);
if (node.equals(localNode)) return nodeData.get(localNode).add(e);
else return rpc.sendAdd(node, e); // 远程调用
}
public boolean contains(Object o) {
String node = hash.getNode((T) o);
if (node.equals(localNode)) return nodeData.get(localNode).contains(o);
else return rpc.sendContains(node, o);
}
}
// 一致性哈希
class ConsistentHash {
private TreeMap ring = new TreeMap<>();
public String getNode(Object key) {
int h = key.hashCode() & Integer.MAX_VALUE;
Map.Entry e = ring.ceilingEntry(h);
return e != null ? e.getValue() : ring.firstEntry().getValue();
}
}
// 高可用:主从复制 + 故障转移
class HADistributedSet {
private String primary;
private List replicas;
private HealthChecker checker;
public boolean add(T e) {
if (!checker.isHealthy(primary)) primary = electNewPrimary();
boolean r = addToNode(primary, e);
CompletableFuture.runAsync(() -> replicas.forEach(n -> addToNode(n, e))); // 异步复制
return r;
}
} 分布式设计要点: