如何在使用 Collectors.groupby() 时迭代流中的对象

如何解决如何在使用 Collectors.groupby() 时迭代流中的对象

我有一个 bean 类 Hotel,其中数据成员为 HotelNameHotelCityHotelContact

现在我想以一种方式将数据保存在 Hashmap 中,其中地图键应该是城市,并且所有酒店名称应该是属于城市的应该是地图值。我可以使用 Collectors.groupby() 做到这一点。但是,我无法获得 HotelName,而是获得了 Hotel 对象地址。请帮助我出错的地方。这是我尝试的代码

class Hotel {
    private String hotelName;
    private String hotelCity;
    private String hotelPhNo;
    /*their getter setter methods*/
}

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","1123");
    Hotel h4 = new Hotel("H4","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","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);
        
    Map<String,List<Hotel>> res = ol.stream().collect(Collectors.groupingBy(Hotel:: getHotelCity));
            
    res.forEach((a,b)->System.out.println("City:"+a+" with Hotels: "+b));

}

有了这个,我得到的输出如下:

City:Ujjain with Hotels: [Hotel@7ba4f24f]
City:Pune with Hotels: [Hotel@3b9a45b3,Hotel@7699a589,Hotel@58372a00]
City:Indore with Hotels: [Hotel@4dd8dc3]
City:Mumbai with Hotels: [Hotel@6d03e736,Hotel@568db2f2]
City:Sehore with Hotels: [Hotel@378bf509]

我想要的期望输出

City:Ujjain with Hotels: [H5]
City:Pune with Hotels: [H1,H3,H8]
City:Indore with Hotels: [H6]
City:Mumbai with Hotels: [H4]
City:Sehore with Hotels: [H7]

请帮忙。我有一个要求,我不想通过覆盖 equals、hashcode 和 tostring 方法来更改 bean 类。覆盖这些方法会更简单地解决此问题,但会寻找替代方法

解决方法

对于这样的输出,您需要 Map<String,List<String>> 数据结构。为此,请在 Collectors.mapping 中使用 Collectors.groupingBy 下游收集器。

Map<String,List<String>> res = ol.stream()
        .collect(Collectors.groupingBy(Hotel:: getHotelCity,Collectors.mapping(Hotel::getHotelName,Collectors.toList())));

注意您需要提供额外的下游收集器 Collectors.toList(),只要 Collectors.mapping 每次都需要它。

结果:

res.forEach((a,b)->System.out.println("City:"+a+" with Hotels: "+b));
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]

如果你仍然想保持原来的 Map<String,List<Hotel>> 结构,但是以不同的方式打印出地图值,你需要改变打印结果的方式:

res.forEach((city,list) -> {
     String hotels = list.stream()
                         .map(Hotel::getHotelName)
                         .collect(Collectors.joining(",","[","]"));
     System.out.println("City:" + city + " with Hotels: " + hotels);
});

最后,几点说明:

  • 用小写首字母命名类字段:private String hotelName;

  • 可以以更短的方式创建 List

    List<Hotel> ol = new ArrayList<>(Arrays.asList(h1,h2,h3,h4,h5,h6,h7,h8));
    
,

这里的问题是 b 代表 List<Hotel>。要打印酒店名称,您应该使用 b 遍历列表 b.forEach(...),然后单独打印每个酒店信息。

您可以像这样更改打印语句:

res.forEach((a,b) -> {
    System.out.println("City:" + a + " with Hotels: ");
    b.forEach(h -> System.out.println("\t" + h.getHotelName()));
});

输出:

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
,

您有 2 个选择。我认为选项 #2 在这里要优越得多。

  1. 不是以 Map<String /* City */,List<Hotel>> 结尾,而是以 Map<String /* City */,List<String /* Name of hotel */>> 结尾。在您的流操作期间,使用下游映射器映射“值”部分:Collectors.mapping(Hotel::getHotelName,Collectors.toList())

  2. 保持数据结构完全相同,但让您的酒店在打印时打印有用的东西;它们目前呈现为 Hotel@7ba4f24f,因为您的 Hotel 类缺少 toString 实现,这是一种糟糕的情况。要修复它,只需添加一个:向您的 Hotel.java 文件添加一个 @Override public String toString() { ... } 方法,该方法打印您想要打印的任何内容。也许就像:return this.hotelName;.

注意:为了让这些事情变得简单,您可以考虑使用 Project Lombok。那么你需要写的是:

@lombok.Data public class Hotel {
    String name,city,phoneNumber;
}

getter、setter 以及 equals、hashCode 和 toString 都只是默默地存在,并具有合理的实现。

免责声明:我为龙目岛项目做出了贡献。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?