程序员面试宝典

一站式面试准备平台

返回分类
Java中级

Java 集合框架

深入理解 Java 集合框架,包括 List、Set、Map 等核心接口及其实现类

2026-03-16
阅读时间: 12分钟

Java 集合框架

集合框架概述

Java 集合框架提供了一套性能优良、使用方便的接口和类,位于 java.util 包中。

主要接口层次

Collection
├── List
├── Set
└── Queue

Map (独立接口)

List 接口

ArrayList

java
import java.util.ArrayList;
import java.util.List;

public class ArrayListExample {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        
        // 添加元素
        list.add("Java");
        list.add("Python");
        list.add("Go");
        
        // 访问元素
        System.out.println(list.get(0)); // Java
        
        // 遍历
        for (String language : list) {
            System.out.println(language);
        }
        
        // 使用 Stream API
        list.stream()
            .filter(lang -> lang.startsWith("J"))
            .forEach(System.out::println);
    }
}

LinkedList

java
import java.util.LinkedList;
import java.util.List;

public class LinkedListExample {
    public static void main(String[] args) {
        LinkedList<String> linkedList = new LinkedList<>();
        
        linkedList.add("First");
        linkedList.add("Second");
        linkedList.addFirst("New First");
        linkedList.addLast("Last");
        
        System.out.println(linkedList.getFirst()); // New First
        System.out.println(linkedList.getLast());  // Last
    }
}

Set 接口

HashSet

java
import java.util.HashSet;
import java.util.Set;

public class HashSetExample {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        
        set.add("Apple");
        set.add("Banana");
        set.add("Apple"); // 重复元素,不会被添加
        
        System.out.println(set.size()); // 2
        System.out.println(set.contains("Apple")); // true
    }
}

TreeSet

java
import java.util.TreeSet;
import java.util.Set;

public class TreeSetExample {
    public static void main(String[] args) {
        Set<Integer> treeSet = new TreeSet<>();
        
        treeSet.add(5);
        treeSet.add(2);
        treeSet.add(8);
        treeSet.add(1);
        
        // TreeSet 会自动排序
        for (Integer num : treeSet) {
            System.out.println(num); // 1, 2, 5, 8
        }
    }
}

Map 接口

HashMap

java
import java.util.HashMap;
import java.util.Map;

public class HashMapExample {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        
        map.put("Alice", 25);
        map.put("Bob", 30);
        map.put("Charlie", 28);
        
        // 获取值
        System.out.println(map.get("Alice")); // 25
        
        // 遍历
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
        
        // 使用 computeIfAbsent
        map.computeIfAbsent("David", k -> 35);
    }
}

ConcurrentHashMap

java
import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;

public class ConcurrentHashMapExample {
    public static void main(String[] args) {
        Map<String, Integer> concurrentMap = new ConcurrentHashMap<>();
        
        // 线程安全的操作
        concurrentMap.put("Key1", 100);
        concurrentMap.putIfAbsent("Key1", 200); // 不会替换
        
        System.out.println(concurrentMap.get("Key1")); // 100
    }
}

集合工具类 Collections

java
import java.util.*;

public class CollectionsExample {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(3, 1, 4, 1, 5, 9);
        
        // 排序
        Collections.sort(list);
        System.out.println("Sorted: " + list);
        
        // 反转
        Collections.reverse(list);
        System.out.println("Reversed: " + list);
        
        // 查找
        int index = Collections.binarySearch(list, 4);
        System.out.println("Index of 4: " + index);
        
        // 创建不可修改的集合
        List<Integer> unmodifiableList = Collections.unmodifiableList(list);
        // unmodifiableList.add(10); // 会抛出 UnsupportedOperationException
    }
}

常见面试题

1. ArrayList 和 LinkedList 的区别

特性ArrayListLinkedList
底层实现动态数组双向链表
随机访问O(1)O(n)
插入/删除O(n)O(1)
内存占用较少较多(需要存储前后指针)

2. HashMap 的工作原理

java
// HashMap 的 put 方法简化版
public V put(K key, V value) {
    // 1. 计算 key 的 hash 值
    int hash = hash(key);
    
    // 2. 计算数组下标
    int index = (n - 1) & hash;
    
    // 3. 处理哈希冲突(链表或红黑树)
    // ...
    
    // 4. 如果 key 已存在,更新值;否则添加新节点
    // ...
    
    // 5. 检查是否需要扩容
    if (++size > threshold) {
        resize();
    }
}

3. 实现 LRU 缓存

java
import java.util.LinkedHashMap;
import java.util.Map;

class LRUCache<K, V> extends LinkedHashMap<K, V> {
    private final int capacity;
    
    public LRUCache(int capacity) {
        super(capacity, 0.75f, true);
        this.capacity = capacity;
    }
    
    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        return size() > capacity;
    }
    
    public static void main(String[] args) {
        LRUCache<Integer, String> cache = new LRUCache<>(3);
        
        cache.put(1, "A");
        cache.put(2, "B");
        cache.put(3, "C");
        
        cache.get(1); // 访问 1,使其成为最近使用的
        
        cache.put(4, "D"); // 这会移除 2(最久未使用)
        
        System.out.println(cache); // {3=C, 1=A, 4=D}
    }
}

最佳实践

  1. 选择合适的集合类型:根据使用场景选择
  2. 使用泛型:避免类型转换错误
  3. 注意线程安全:多线程环境下使用并发集合
  4. 初始化容量:对于已知大小的集合,指定初始容量
  5. 使用不可变集合:当集合不需要修改时

相关标签