Java集合框架(Java Collections Framework, JCF)位于java.util
包中,包含三大核心接口:
Collection
├── List
│ ├── ArrayList
│ ├── LinkedList
│ └── Vector
│ └── Stack
├── Set
│ ├── HashSet
│ │ └── LinkedHashSet
│ └── SortedSet
│ └── TreeSet
└── Queue
├── Deque
│ ├── ArrayDeque
│ └── LinkedList
└── PriorityQueue
Map
├── HashMap
│ └── LinkedHashMap
├── Hashtable
└── SortedMap
└── TreeMap
// 创建ArrayList
List<String> arrayList = new ArrayList<>();
// 添加元素
arrayList.add("Java");
arrayList.add("Python");
arrayList.add(1, "C++"); // 在指定位置插入
// 访问元素
String lang = arrayList.get(0); // "Java"
// 遍历
for (String s : arrayList) {
System.out.println(s);
}
// 删除元素
arrayList.remove("Python");
arrayList.remove(0);
// 创建LinkedList
List<String> linkedList = new LinkedList<>();
// 特有方法
LinkedList<String> list = (LinkedList<String>) linkedList;
list.addFirst("First");
list.addLast("Last");
String first = list.getFirst();
String last = list.getLast();
Set<String> hashSet = new HashSet<>();
hashSet.add("Apple");
hashSet.add("Banana");
hashSet.add("Apple"); // 重复元素不会被添加
System.out.println(hashSet); // [Apple, Banana]
Set<Integer> treeSet = new TreeSet<>((a, b) -> b - a); // 自定义排序
treeSet.add(5);
treeSet.add(2);
treeSet.add(8);
System.out.println(treeSet); // [8, 5, 2]
Map<String, Integer> hashMap = new HashMap<>();
hashMap.put("Alice", 25);
hashMap.put("Bob", 30);
hashMap.put("Charlie", 28);
// 获取值
int age = hashMap.get("Bob");
// 遍历
for (Map.Entry<String, Integer> entry : hashMap.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
Map<String, Integer> treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
treeMap.put("Banana", 3);
treeMap.put("apple", 5);
treeMap.put("Orange", 2);
System.out.println(treeMap); // {apple=5, Banana=3, Orange=2}
// List转Set(去重)
List<String> listWithDuplicates = Arrays.asList("A", "B", "A", "C");
Set<String> set = new HashSet<>(listWithDuplicates); // [A, B, C]
// Set转List
List<String> listFromSet = new ArrayList<>(set);
// 数组转List
String[] array = {"Java", "Python", "C++"};
List<String> list = Arrays.asList(array); // 固定大小List
List<String> mutableList = new ArrayList<>(Arrays.asList(array));
// List转数组
String[] newArray = list.toArray(new String[0]);
// Map的key转Set
Set<String> keys = hashMap.keySet();
// Map的entry转Set
Set<Map.Entry<String, Integer>> entries = hashMap.entrySet();
// Set转Map(需要元素包含键值信息)
Set<Pair<String, Integer>> pairSet = new HashSet<>();
// ...添加元素
Map<String, Integer> mapFromSet = pairSet.stream()
.collect(Collectors.toMap(Pair::getKey, Pair::getValue));
List<String> immutableList = List.of("A", "B", "C");
Set<Integer> immutableSet = Set.of(1, 2, 3);
Map<String, Integer> immutableMap = Map.of("A", 1, "B", 2);
// 尝试修改会抛出UnsupportedOperationException
// immutableList.add("D"); // 错误
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
List<String> unmodifiableList = Collections.unmodifiableList(list);
List<String> languages = Arrays.asList("Java", "Python", "C++", "JavaScript", "Ruby");
// 过滤长度大于3的元素
List<String> filtered = languages.stream()
.filter(s -> s.length() > 3)
.collect(Collectors.toList()); // [Java, Python, JavaScript, Ruby]
// 转换为大写
List<String> upperCase = languages.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
// 统计
long count = languages.stream().count();
Optional<String> max = languages.stream().max(Comparator.naturalOrder());
// 求和
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream().reduce(0, Integer::sum);
// 按长度分组
Map<Integer, List<String>> groupByLength = languages.stream()
.collect(Collectors.groupingBy(String::length));
// {2=[C++], 4=[Java, Ruby], 6=[Python], 10=[JavaScript]}
// 分区(满足条件的和其他的)
Map<Boolean, List<String>> partition = languages.stream()
.collect(Collectors.partitioningBy(s -> s.startsWith("J")));
// {false=[Python, C++, Ruby], true=[Java, JavaScript]}
// 顺序流
long count = languages.stream().filter(s -> s.length() > 3).count();
// 并行流(大数据量性能更好)
long parallelCount = languages.parallelStream().filter(s -> s.length() > 3).count();
List<String> list = Arrays.asList("A", "B", "C");
String[] array = list.toArray(new String[0]); // 推荐使用空数组
String[] array = list.stream().toArray(String[]::new);
String[] array = {"A", "B", "C"};
// 固定大小List(不可修改)
List<String> asList = Arrays.asList(array);
// 可变List
List<String> mutableList = new ArrayList<>(Arrays.asList(array));
List<String> list = Arrays.stream(array).collect(Collectors.toList());
// 去重
Set<String> set = Arrays.stream(array).collect(Collectors.toSet());
Object[] elementData
newCapacity = oldCapacity + (oldCapacity >> 1)
(约1.5倍)Integer.MAX_VALUE - 8
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
// ...
}
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
newTab[e.hash & (newCap - 1)]
操作 | ArrayList | LinkedList |
---|---|---|
get(int) | O(1) | O(n) |
add(E) | 平均O(1) | O(1) |
add(int, E) | O(n) | O(1) |
remove(int) | O(n) | O(1) |
内存占用 | 较小(仅数组) | 较大(节点开销) |
特性 | HashSet | LinkedHashSet | TreeSet |
---|---|---|---|
底层实现 | HashMap | LinkedHashMap | TreeMap |
顺序 | 无序 | 插入顺序 | 自然/自定义排序 |
时间复杂度 | O(1) | O(1) | O(log n) |
线程安全 | 否 | 否 | 否 |
特性 | HashMap | LinkedHashMap | TreeMap | Hashtable |
---|---|---|---|---|
底层实现 | 数组+链表+红黑树 | 链表+哈希表 | 红黑树 | 数组+链表 |
顺序 | 无序 | 插入/访问顺序 | 键排序 | 无序 |
线程安全 | 否 | 否 | 否 | 是 |
允许null | 是 | 是 | 否 | 否 |
// 线程安全但性能较差
Vector<String> vector = new Vector<>();
Hashtable<String, Integer> hashtable = new Hashtable<>();
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
Map<String, Integer> syncMap = Collections.synchronizedMap(new HashMap<>());
// 写时复制,适合读多写少场景
List<String> cowList = new CopyOnWriteArrayList<>();
// 分段锁实现高并发
Map<String, Integer> concurrentMap = new ConcurrentHashMap<>();
// 阻塞队列
BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);
queue.put("item"); // 阻塞直到空间可用
String item = queue.take(); // 阻塞直到元素可用
初始化合适容量:
new ArrayList<>(100); // 避免频繁扩容
new HashMap<>(32, 0.75f);
使用forEach代替迭代器:
// Java 8+
list.forEach(System.out::println);
map.forEach((k, v) -> System.out.println(k + ": " + v));
避免在循环中修改集合:
// 错误方式 - 可能抛出ConcurrentModificationException
for (String item : list) {
if (condition) {
list.remove(item);
}
}
// 正确方式 - 使用迭代器
Iterator<String> it = list.iterator();
while (it.hasNext()) {
if (condition) {
it.remove();
}
}
Arrays.asList返回固定大小List:
List<String> list = Arrays.asList("A", "B", "C");
// list.add("D"); // 抛出UnsupportedOperationException
集合元素可变性问题:
Set<Date> dates = new HashSet<>();
Date now = new Date();
dates.add(now);
now.setTime(now.getTime() + 1000); // 修改后影响集合行为
equals和hashCode不一致:
class Person {
String name;
// 如果只重写equals不重写hashCode,会导致HashSet/HashMap行为异常
}
map.computeIfAbsent(key, k -> new ArrayList<>()).add(value);
list.removeIf(e -> e.length() > 5);
List<String> list = List.of("A", "B", "C");
Set<Integer> set = Set.of(1, 2, 3);
Map<String, Integer> map = Map.of("A", 1, "B", 2);
List<String> copy = List.copyOf(originalList);
List<String> list = stream.toList(); // 替代collect(Collectors.toList())
通过深入理解Java集合框架的设计原理和使用方法,开发者可以编写出更高效、更健壮的代码。集合框架是Java编程中最常用的工具之一,掌握其特性和最佳实践对提高开发效率至关重要。