Java 集合框架(List, Set, Map)练习题
核心收获:熟练掌握 Java 集合框架(List, Set, Map)
练习1 — List 去重与保留顺序
移除列表中的重复元素并保持首次出现的顺序,使用 LinkedHashSet 构造函数或 Stream 的 distinct(),对比 HashSet 丢失顺序的场景。
//练习1:List去重与保留顺序//测试数据List<String>duplicateList=Arrays.asList("A","B","A","C","B","D","E","T","G","F","Y","G");//方法1:使用LinkedHashSet(底层基于插入顺序的哈希表,天然保序)List<String>distinctWithOrderOne=newArrayList<>(newLinkedHashSet<>(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=newArrayList<>(newHashSet<>(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)。
//练习2:Map的安全获取与默认值//测试数据Map<String,String>userConfig=newHashMap<>();userConfig.put("theme","dark");userConfig.put("fontSize","16");//方法1:getOrDefault,仅查询不写入MapStringtheme=userConfig.getOrDefault("theme","light");StringunknownKey=userConfig.getOrDefault("unknownKey","defaultValue");System.out.println("theme配置:"+theme);System.out.println("不存在的key默认值:"+unknownKey);//方法2:computeIfAbsent,若key不存在则写入默认值到Map,后续直接复用StringcacheConfig=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 查找)。
//练习3集合求交集与差集//测试数据List<String>tagsOne=newArrayList<>(Arrays.asList("Java","Spring","AI","MySQL"));List<String>tagsTwo=newArrayList<>(Arrays.asList("Spring","Redis","Java","Kafka"));//性能优化:先转HashSet,将contains操作从O(n)降为O(1),适配大数据量场景Set<String>tagSetOne=newHashSet<>(tagsOne);Set<String>tagSetTwo=newHashSet<>(tagsTwo);//1:求交集(共同标签)Set<String>intersection=newHashSet<>(tagSetOne);intersection.retainAll(tagSetTwo);System.out.println("共同标签:"+intersection);//2:求差集(tagOne独有的标签)Set<String>difference=newHashSet<>(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 并处理键冲突策略。
//练习4:List转Map分组与映射//测试数据List<Order>orders=Arrays.asList(newOrder(1L,1,99.9),newOrder(2L,1,199.9),newOrder(3L,2,299.9),newOrder(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]}