核心收获:熟练掌握 Java 集合框架(List, Set, Map)
练习1 --- List 去重与保留顺序
移除列表中的重复元素并保持首次出现的顺序,使用 LinkedHashSet 构造函数或 Stream 的 distinct(),对比 HashSet 丢失顺序的场景。
java
//练习1:List去重与保留顺序
//测试数据
List<String> duplicateList = Arrays.asList("A", "B", "A", "C", "B", "D", "E", "T", "G", "F", "Y", "G");
//方法1:使用LinkedHashSet(底层基于插入顺序的哈希表,天然保序)
List<String> distinctWithOrderOne = new ArrayList<>(new LinkedHashSet<>(duplicateList));
System.out.println("LinkedHashSet去重保序结果:" + distinctWithOrderOne);
//方法2:使用Stream.distinct()(底层基于LinkedHashSet实现,同样保序)
List<String> distinctWithOrderTwo = duplicateList.stream().distinct().collect(Collectors.toList());
System.out.println("Stream.distinct()去重保序结果:" + distinctWithOrderTwo);
//方法3:对比:普通HashSet会丢失插入顺序
List<String> distinctNoOrder = new ArrayList<>(new HashSet<>(duplicateList));
System.out.println("HashSet去重丢失顺序结果:" + distinctNoOrder);
//输出结果:
//LinkedHashSet去重保序结果:[A, B, C, D, E, T, G, F, Y]
//Stream.distinct()去重保序结果:[A, B, C, D, E, T, G, F, Y]
//HashSet去重丢失顺序结果:[A, B, C, D, E, F, G, T, Y]
练习2 --- Map 安全获取与默认值
从 Map 中获取用户配置,若 Key 不存在则返回默认配置对象,使用 Map.getOrDefault() 或 computeIfAbsent() 避免空指针异常(NPE)。
java
//练习2:Map的安全获取与默认值
//测试数据
Map<String, String> userConfig = new HashMap<>();
userConfig.put("theme", "dark");
userConfig.put("fontSize", "16");
//方法1:getOrDefault,仅查询不写入Map
String theme = userConfig.getOrDefault("theme", "light");
String unknownKey = userConfig.getOrDefault("unknownKey", "defaultValue");
System.out.println("theme配置:" + theme);
System.out.println("不存在的key默认值:" + unknownKey);
//方法2:computeIfAbsent,若key不存在则写入默认值到Map,后续直接复用
String cacheConfig = userConfig.computeIfAbsent("cacheExpire", k -> "3600");
System.out.println("新增的缓存配置:" + cacheConfig);
System.out.println("Map最终内容:" + userConfig);
//输出结果:
//theme配置:dark
//不存在的key默认值:defaultValue
//新增的缓存配置:3600
//Map最终内容:{cacheExpire=3600, theme=dark, fontSize=16}
练习3 --- 集合求交集与差集
找出两个用户标签列表(List)的共同标签(交集)和独有标签(差集),使用 retainAll() / removeAll() 或 Stream 的 filter + contains,注意大数据量下的性能优化(转为 HashSet 查找)。
java
//练习3集合求交集与差集
//测试数据
List<String> tagsOne = new ArrayList<>(Arrays.asList("Java", "Spring", "AI", "MySQL"));
List<String> tagsTwo = new ArrayList<>(Arrays.asList("Spring", "Redis", "Java", "Kafka"));
//性能优化:先转HashSet,将contains操作从O(n)降为O(1),适配大数据量场景
Set<String> tagSetOne = new HashSet<>(tagsOne);
Set<String> tagSetTwo = new HashSet<>(tagsTwo);
//1:求交集(共同标签)
Set<String> intersection = new HashSet<>(tagSetOne);
intersection.retainAll(tagSetTwo);
System.out.println("共同标签:" + intersection);
//2:求差集(tagOne独有的标签)
Set<String> difference = new HashSet<>(tagSetOne);
difference.removeAll(tagSetTwo);
System.out.println("tagOne独有的标签:" + difference);
//3:Stream写法实现交集
List<String> streamIntersection = tagsOne.stream().filter(tagSetTwo::contains).collect(Collectors.toList());
System.out.println("Stream实现交集:" + streamIntersection);
//4:Stream写法实现差集
List<String> streamDifference = tagsOne.stream().filter(tag -> !tagSetTwo.contains(tag)).collect(Collectors.toList());
System.out.println("Stream实现差集:" + streamDifference);
//输出结果
//共同标签:[Java, Spring]
//tagOne独有的标签:[MySQL, AI]
//Stream实现交集:[Java, Spring]
//Stream实现差集:[AI, MySQL]
练习4 --- List 转 Map 分组与映射
将订单列表按"状态"分组统计总金额,使用 Collectors.groupingBy 嵌套 Collectors.summingDouble;或将列表直接转为 Map<ID, Object> 以便快速查找,使用 Collectors.toMap 并处理键冲突策略。
java
//练习4:List转Map分组与映射
//测试数据
List<Order> orders = Arrays.asList(new Order(1L, 1, 99.9),
new Order(2L, 1, 199.9),
new Order(3L, 2, 299.9),
new Order(4L, 2, 399.9));
//1:按订单状态分组,统计每个状态的总金额
Map<Integer, Double> statusTotalMap = orders.stream().collect(Collectors.groupingBy(Order::status, Collectors.summingDouble(Order::amount)));
System.out.println("按订单状态分组总金额:" + statusTotalMap);
//2:转成ID-订单的快速查找Map,处理键冲突
Map<Long, Order> idToOrderMap = orders.stream().collect(Collectors.toMap(Order::id, order -> order, (oldVal, newVal) -> oldVal));
System.out.println("ID映射订单Map:" + idToOrderMap);
//输出结果:
//按订单状态分组总金额:{1=299.8, 2=699.8}
//ID映射订单Map:{1=Order[id=1, status=1, amount=99.9],
// 2=Order[id=2, status=1, amount=199.9],
// 3=Order[id=3, status=2, amount=299.9],
// 4=Order[id=4, status=2, amount=399.9]}