使用Collectors.groupingBy()分组酒店数据时,如何在不修改Bean类的情况下获取酒店名称而非对象地址
解决HashMap分组后显示Hotel对象内存地址的问题
我明白你的问题了——你现在用Collectors.groupingBy()分组后得到的是Hotel对象列表,打印时显示的是对象的内存地址,而且你不能修改Hotel类的任何代码对吧?别担心,我们可以通过调整Stream收集器的用法来解决这个问题。
问题根源
你当前的代码里,groupingBy直接将每个城市对应的Hotel对象收集为列表:
Map<String, List<Hotel>> res = ol.stream().collect(Collectors.groupingBy(Hotel::getHotelCity));
打印这个列表时,因为Hotel类没有重写toString()方法,JVM会调用Object类的默认实现,输出Hotel@哈希值这种格式的内存地址标识,这就是你看到的结果。
解决方案
我们可以在groupingBy中添加第二个参数:Collectors.mapping()收集器。这个收集器的作用是将分组后的每个Hotel对象映射为我们需要的酒店名称字符串,再通过Collectors.toList()收集为字符串列表。这样最终的Map类型会变成Map<String, List<String>>,完全符合你的需求,而且不需要修改Hotel类。
修改后的完整main方法代码如下:
public static void main(String[] args) { List<Hotel> ol = new ArrayList<Hotel>(); Hotel h1 = new Hotel("H1","Pune","123"); Hotel h2 = new Hotel("H2","Mumbai","109"); Hotel h3 = new Hotel("H3","Pune","1123"); Hotel h4 = new Hotel("H4","Mumbai","123"); Hotel h5 = new Hotel("H5","Ujjain","123"); Hotel h6 = new Hotel("H6","Indore","123"); Hotel h7 = new Hotel("H7","Sehore","123"); Hotel h8 = new Hotel("H8","Pune","123"); ol.add(h1); ol.add(h2); ol.add(h3); ol.add(h4); ol.add(h5); ol.add(h6); ol.add(h7); ol.add(h8); // 关键修改:添加mapping收集器转换为酒店名称 Map<String, List<String>> res = ol.stream() .collect(Collectors.groupingBy( Hotel::getHotelCity, Collectors.mapping(Hotel::getHotelName, Collectors.toList()) )); res.forEach((a,b)->System.out.println("City:"+a+" with Hotels: "+b)); }
运行结果
执行上述代码后,输出会和你的期望(修正了Mumbai的酒店列表)完全一致:
City:Ujjain with Hotels: [H5] City:Pune with Hotels: [H1, H3, H8] City:Indore with Hotels: [H6] City:Mumbai with Hotels: [H2, H4] City:Sehore with Hotels: [H7]
为什么这个方法可行?
Collectors.mapping()是一个下游收集器,它会在groupingBy完成分组后,对每个组内的元素进行转换操作——这里就是调用getHotelName()获取酒店名称字符串,然后再用Collectors.toList()把这些字符串收集成列表。整个过程完全不需要修改Hotel类的任何方法,完美满足你的限制条件。
内容的提问来源于stack exchange,提问作者gaurav kulkarni
相关产品推荐
相关产品推荐

