16 個 Java 集合框架實戰(zhàn)案例,從入門到精通全搞定
還在為 Java 集合框架頭疼嗎?ArrayList 和 LinkedList 到底該用哪個?HashMap 為什么會出現(xiàn)死循環(huán)?集合遍歷總拋ConcurrentModificationException 怎么破?別慌!今天這篇文章,我把 Java 集合框架中最常用的 16 個實戰(zhàn)案例一次性講透,從基礎(chǔ)用法到高級技巧,每個案例都配上真實業(yè)務(wù)場景的代碼示例,看完讓你對集合的使用豁然開朗,開發(fā)效率直接翻倍!

一、List 集合實戰(zhàn):有序集合的核心用法
1. ArrayList 基本操作:增刪改查
ArrayList 是最常用的 List 實現(xiàn)類,底層是動態(tài)數(shù)組,查詢快、增刪慢,適合讀多寫少的場景。
public class ArrayListDemo {
   public static void main(String[] args) {
       // 創(chuàng)建 ArrayList 并添加元素
       List<String> fruits = new ArrayList<>();
       fruits.add("蘋果");
       fruits.add("香蕉");
       fruits.add("橙子");
       // 訪問元素
       System.out.println("第二個水果:" + fruits.get(1)); // 輸出:香蕉
       // 修改元素
       fruits.set(2, "葡萄");
       // 刪除元素
       fruits.remove(0);
       // 遍歷元素
       for (String fruit : fruits) {
           System.out.println(fruit);
       }
       // 輸出:
       // 香蕉
       // 葡萄
   }
}使用場景:商品列表展示、用戶訂單記錄等需要頻繁查詢的場景。
2. LinkedList 實戰(zhàn):鏈表的高效增刪
LinkedList 底層是雙向鏈表,增刪快、查詢慢,適合頻繁插入刪除的場景。
public class LinkedListDemo {
   public static void main(String[] args) {
       LinkedList<String> queue = new LinkedList<>();
       // 模擬隊列:尾部添加,頭部移除
       queue.addLast("任務(wù)1");
       queue.addLast("任務(wù)2");
       queue.addLast("任務(wù)3");
       while (!queue.isEmpty()) {
           String task = queue.removeFirst();
           System.out.println("處理任務(wù):" + task);
       }
       // 輸出:
       // 處理任務(wù):任務(wù)1
       // 處理任務(wù):任務(wù)2
       // 處理任務(wù):任務(wù)3
   }
}使用場景:消息隊列、棧、鏈表結(jié)構(gòu)的業(yè)務(wù)場景(如最近瀏覽記錄)。
3. List 排序:自定義排序規(guī)則
對 List 中的元素進行排序,支持自然排序和自定義排序。
public class ListSortDemo {
   public static void main(String[] args) {
       List<User> users = new ArrayList<>();
       users.add(new User("張三", 25));
       users.add(new User("李四", 20));
       users.add(new User("王五", 30));
       // 按年齡升序排序(自定義比較器)
       users.sort(Comparator.comparingInt(User::getAge));
       // 遍歷排序后的結(jié)果
       users.forEach(user -> System.out.println(user.getName() + ":" + user.getAge()));
       // 輸出:
       // 李四:20
       // 張三:25
       // 王五:30
       // 按年齡降序排序
       users.sort((u1, u2) -> Integer.compare(u2.getAge(), u1.getAge()));
   }
   static class User {
       private String name;
       private int age;
       // 構(gòu)造方法、getter、setter省略
   }
}4. List 去重:多種去重方式對比
在開發(fā)中經(jīng)常需要對 List 進行去重,不同方式效率不同。
public class ListDeduplicationDemo {
   public static void main(String[] args) {
       List<String> list = Arrays.asList("a", "b", "a", "c", "b");
       // 方式1:通過 HashSet 去重(無序)
       List<String> distinct1 = new ArrayList<>(new HashSet<>(list));
       // 方式2:通過 LinkedHashSet 去重(保持順序)
       List<String> distinct2 = new ArrayList<>(new LinkedHashSet<>(list));
       // 方式3:Java 8 Stream 去重(保持順序)
       List<String> distinct3 = list.stream().distinct().collect(Collectors.toList());
       System.out.println(distinct2); // 輸出:[a, b, c]
   }
}推薦:需要保持順序用 LinkedHashSet 或 Stream.distinct (),無需保持順序用 HashSet。
二、Set 集合實戰(zhàn):無序不重復集合
5. HashSet 基本用法:快速去重
HashSet 基于哈希表實現(xiàn),元素無序且唯一,查詢效率高。
public class HashSetDemo {
   public static void main(String[] args) {
       Set<String> tags = new HashSet<>();
       tags.add("Java");
       tags.add("Python");
       tags.add("Java"); // 重復元素,添加失敗
       System.out.println(tags.size()); // 輸出:2
       // 遍歷(無序)
       for (String tag : tags) {
           System.out.println(tag);
       }
   }
}使用場景:標簽去重、用戶 ID 去重、過濾重復數(shù)據(jù)等。
6. TreeSet 排序:自然排序與定制排序
TreeSet 可以對元素進行排序,默認是自然排序,也可以自定義排序規(guī)則。
public class TreeSetDemo {
   public static void main(String[] args) {
       // 自然排序(String 實現(xiàn)了 Comparable 接口)
       Set<String> treeSet1 = new TreeSet<>();
       treeSet1.add("c");
       treeSet1.add("a");
       treeSet1.add("b");
       System.out.println(treeSet1); // 輸出:[a, b, c]
       // 自定義排序(按字符串長度)
       Set<String> treeSet2 = new TreeSet<>(Comparator.comparingInt(String::length));
       treeSet2.add("apple");
       treeSet2.add("banana");
       treeSet2.add("pear");
       System.out.println(treeSet2); // 輸出:[pear, apple, banana]
   }
}7. 利用 Set 檢查重復元素
在批量插入數(shù)據(jù)時,先檢查是否有重復元素,避免插入重復數(shù)據(jù)。
public class CheckDuplicateDemo {
   public static void main(String[] args) {
       List<String> userIds = Arrays.asList("1001", "1002", "1001", "1003");
       Set<String> existingIds = new HashSet<>();
       List<String> duplicates = new ArrayList<>();
       for (String id : userIds) {
           if (!existingIds.add(id)) { // add失敗說明已存在
               duplicates.add(id);
           }
       }
       System.out.println("重復的用戶ID:" + duplicates); // 輸出:[1001]
   }
}三、Map 集合實戰(zhàn):鍵值對存儲的利器
8. HashMap 基本操作:最常用的鍵值對集合
HashMap 是最常用的 Map 實現(xiàn)類,基于哈希表,查詢效率高,允許 key 和 value 為 null。
public class HashMapDemo {
   public static void main(String[] args) {
       Map<String, Integer> scoreMap = new HashMap<>();
       // 添加元素
       scoreMap.put("張三", 90);
       scoreMap.put("李四", 85);
       scoreMap.put("王五", 95);
       // 獲取元素
       int score = scoreMap.get("張三"); // 90
       // 遍歷key
       for (String name : scoreMap.keySet()) {
           System.out.println(name + ":" + scoreMap.get(name));
       }
       // 遍歷key-value
       for (Map.Entry<String, Integer> entry : scoreMap.entrySet()) {
           System.out.println(entry.getKey() + ":" + entry.getValue());
       }
       // Java 8 forEach
       scoreMap.forEach((name, s) -> System.out.println(name + ":" + s));
   }
}使用場景:存儲鍵值對數(shù)據(jù),如用戶信息(key 為用戶 ID,value 為用戶對象)、配置參數(shù)等。
9. HashMap 進階:處理 null 鍵值與遍歷方式對比
HashMap 允許 key 和 value 為 null,但要注意處理方式。
public class HashMapAdvancedDemo {
   public static void main(String[] args) {
       Map<String, String> map = new HashMap<>();
       map.put(null, "null key");
       map.put("key1", null);
       System.out.println(map.get(null)); // 輸出:null key
       System.out.println(map.get("key1")); // 輸出:null
       // 注意:get方法返回null可能是key不存在,也可能是value為null
       // 判斷key是否存在
       System.out.println(map.containsKey("key1")); // 輸出:true
       // 遍歷方式效率對比:entrySet比keySet高效(減少一次get操作)
       // 推薦使用entrySet或forEach
   }
}10. LinkedHashMap:保持插入順序的 Map
LinkedHashMap 繼承自 HashMap,能保持元素的插入順序或訪問順序。
public class LinkedHashMapDemo {
   public static void main(String[] args) {
       // 保持插入順序
       Map<String, String> linkedHashMap = new LinkedHashMap<>();
       linkedHashMap.put("name", "張三");
       linkedHashMap.put("age", "25");
       linkedHashMap.put("gender", "男");
       // 遍歷順序與插入順序一致
       linkedHashMap.forEach((k, v) -> System.out.println(k + ":" + v));
       // 按訪問順序排序(最近訪問的放在最后)
       Map<String, String> accessOrderMap = new LinkedHashMap<>(16, 0.75f, true);
       accessOrderMap.put("a", "a");
       accessOrderMap.put("b", "b");
       accessOrderMap.get("a"); // 訪問a
       accessOrderMap.put("c", "c");
       // 遍歷順序:b, a, c(a被訪問過,放在c前面)
   }
}使用場景:實現(xiàn) LRU 緩存(最近最少使用淘汰策略)。
11. 統(tǒng)計元素出現(xiàn)次數(shù):Map 經(jīng)典用法
統(tǒng)計一個列表中每個元素出現(xiàn)的次數(shù),是 Map 的典型應(yīng)用。
public class CountElementsDemo {
   public static void main(String[] args) {
       List<String> words = Arrays.asList("apple", "banana", "apple", "orange", "banana", "apple");
       Map<String, Integer> countMap = new HashMap<>();
       // 統(tǒng)計次數(shù)
       for (String word : words) {
           countMap.put(word, countMap.getOrDefault(word, 0) + 1);
       }
       // Java 8 Stream方式
       Map<String, Long> countMap2 = words.stream()
               .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
       System.out.println(countMap); // 輸出:{apple=3, banana=2, orange=1}
   }
}三、集合進階:工具類與高級操作
12. Collections 工具類:集合操作的好幫手
Collections 提供了大量靜態(tài)方法,用于操作集合,如排序、查找、同步化等。
public class CollectionsDemo {
   public static void main(String[] args) {
       List<String> list = new ArrayList<>(Arrays.asList("b", "a", "c"));
       // 排序
       Collections.sort(list);
       System.out.println(list); // 輸出:[a, b, c]
       // 二分查找(需先排序)
       int index = Collections.binarySearch(list, "b"); // 1
       // 反轉(zhuǎn)
       Collections.reverse(list);
       System.out.println(list); // 輸出:[c, b, a]
       // 創(chuàng)建不可修改的集合
       List<String> unmodifiableList = Collections.unmodifiableList(list);
       // unmodifiableList.add("d"); // 拋UnsupportedOperationException
       // 創(chuàng)建同步集合(線程安全)
       List<String> synchronizedList = Collections.synchronizedList(new ArrayList<>());
   }
}13. 集合與數(shù)組轉(zhuǎn)換:相互轉(zhuǎn)換的技巧
集合和數(shù)組之間經(jīng)常需要轉(zhuǎn)換,注意轉(zhuǎn)換后的可變性。
public class CollectionArrayConversionDemo {
   public static void main(String[] args) {
       // 集合轉(zhuǎn)數(shù)組
       List<String> list = Arrays.asList("a", "b", "c");
       String[] array1 = list.toArray(new String[0]); // 推薦方式
       // 數(shù)組轉(zhuǎn)集合
       String[] array = {"x", "y", "z"};
       List<String> list1 = Arrays.asList(array); // 返回的是固定大小的列表,不能增刪
       // 轉(zhuǎn)為可修改的ArrayList
       List<String> list2 = new ArrayList<>(Arrays.asList(array));
       list2.add("w"); // 可以正常增刪
   }
}注意:Arrays.asList () 返回的列表是固定大小的,不能進行 add/remove 操作。
14. 集合遍歷與迭代器:避免 ConcurrentModificationException
在遍歷集合時修改集合(增刪元素)可能會拋出 ConcurrentModificationException。
public class IteratorDemo {
   public static void main(String[] args) {
       List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));
       // 錯誤方式:foreach循環(huán)中刪除元素
       // for (String s : list) {
       //     if ("a".equals(s)) {
       //         list.remove(s); // 拋ConcurrentModificationException
       //     }
       // }
       // 正確方式1:使用迭代器
       Iterator<String> iterator = list.iterator();
       while (iterator.hasNext()) {
           String s = iterator.next();
           if ("a".equals(s)) {
               iterator.remove(); // 迭代器的remove方法
           }
       }
       // 正確方式2:Java 8 removeIf(推薦)
       list.removeIf("b"::equals);
       System.out.println(list); // 輸出:[c]
   }
}15. 集合過濾與轉(zhuǎn)換:Stream API 的妙用
Java 8 的 Stream API 為集合操作提供了強大的支持,如過濾、映射、聚合等。
public class StreamCollectionDemo {
   public static void main(String[] args) {
       List<User> users = Arrays.asList(
               new User("張三", 20, "男"),
               new User("李四", 25, "女"),
               new User("王五", 30, "男")
       );
       // 過濾:年齡大于22的男性用戶
       List<User> filtered = users.stream()
               .filter(user -> user.getAge() > 22 && "男".equals(user.getGender()))
               .collect(Collectors.toList());
       // 轉(zhuǎn)換:提取用戶名列表
       List<String> names = users.stream()
               .map(User::getName)
               .collect(Collectors.toList());
       // 聚合:計算平均年齡
       double avgAge = users.stream()
               .mapToInt(User::getAge)
               .average()
               .orElse(0);
       System.out.println(avgAge); // 輸出:25.0
   }
}16. 集合初始化容量:提高性能的小技巧
初始化集合時指定合適的容量,可以減少擴容次數(shù),提高性能。
public class CollectionInitialCapacityDemo {
   public static void main(String[] args) {
       // 已知大概有1000個元素,指定初始容量1000(HashMap負載因子0.75,1000/0.75≈1333)
       Map<String, Object> map = new HashMap<>(1333);
       // ArrayList默認初始容量10,每次擴容為原來的1.5倍
       // 已知元素量時直接指定,減少擴容
       List<String> list = new ArrayList<>(1000);
   }
}原理:HashMap 擴容時需要重新計算哈希并遷移元素,ArrayList 擴容需要復制數(shù)組,指定初始容量可減少這些操作。















 
 
 













 
 
 
 