【问题标题】:Java 8 Lambda to create a Map where Value is a Wrapper Object of a listJava 8 Lambda 创建一个 Map,其中 Value 是列表的包装器对象
【发布时间】:2018-05-11 20:15:21
【问题描述】:

我有这个地址类作为列表,我想创建一个地图,其中街道名称作为键,所有地址对象的列表作为街道名称的一部分。假设我得到地址作为列表,所以我有一个地址列表。

public class Address{
    private String streetName;
    private String city;
    private String country;
    private String zipCode;
    public String getStreetName() {
        return streetName;
    }
    public void setStreetName(String streetName) {
        this.streetName = streetName;
    }
    public String getCity() {
        return city;
    }
    public void setCity(String city) {
        this.city = city;
    }
    public String getCountry() {
        return country;
    }
    public void setCountry(String country) {
        this.country = country;
    }
    public String getZipCode() {
        return zipCode;
    }
    public void setZipCode(String zipCode) {
        this.zipCode = zipCode;
    }

}

I was able to do this using Lambda with the below Code

Map<String, List<Address>> resultMap =
addressList.stream().collect(Collectors.groupingBy(address-> address.getStreetName())); // This creates Map with street name as key and list of addresses as values

我需要在地址顶部创建一个包装器,使其看起来像

public class AddressWrapper {
     private String streetName;
    private List<Address> addressWrapperList;
    public String getStreetName() {
        return streetName;
    }
    public void setStreetName(String streetName) {
        this.streetName = streetName;
    }
    public List<Address> getAddressWrapperList() {
        return addressWrapperList;
    }
    public void setAddressWrapperList(List<Address> addressWrapperList) {
        this.addressWrapperList= addressWrapperList;
    }
}

现在有了我拥有的地址列表,我该如何创建一个地图以便 而不是街道名称作为键和属于该街道名称的地址列表作为值,我想创建一个以街道名称作为键但值作为 addressWrapperList 的地图(这是一个地址列表)

【问题讨论】:

  • Map&lt;String, AddressWrapper&gt;?但老实说,为什么不使用Map&lt;String, List&lt;Address&gt;&gt;
  • 这就是我最初拥有的,但为了满足其他功能,我不得不构建这样的地图结构,因此寻找选项。

标签: java lambda java-8


【解决方案1】:

一种解决方法是从groupingBy 操作的结果创建一个流并收集到Map,将值映射器函数指定为AddressWrapper

Map<String, AddressWrapper> result = addressList.stream()
                .collect(Collectors.groupingBy(Address::getStreetName))
                .entrySet()
                .stream()
                .collect(Collectors.toMap(Map.Entry::getKey, e -> {
                    AddressWrapper addressWrapper = new AddressWrapper();
                    addressWrapper.setStreetName(e.getKey());
                    addressWrapper.setAddressWrapperList(e.getValue());
                    return addressWrapper;
                }));

您可以通过创建带有签名public AddressWrapper(String streetName, List&lt;Address&gt; addressWrapperList) {...} 的构造函数来简化值映射器逻辑。

那么代码就变成了:

Map<String, AddressWrapper> result = addressList.stream()
                .collect(Collectors.groupingBy(Address::getStreetName))
                .entrySet()
                .stream()
                .collect(Collectors.toMap(Map.Entry::getKey, 
                              e -> new AddressWrapper(e.getKey(), e.getValue())));

此外,您还可以使用toMap 收集器达到相同的结果,如下所示:

Map<String, AddressWrapper> resultSet = addressList.stream()
      .collect(Collectors.toMap(Address::getStreetName,
              e -> new AddressWrapper(e.getStreetName(),
                      new ArrayList<>(Collections.singletonList(e))),
            (left, right) -> {
                left.getAddressWrapperList().addAll(right.getAddressWrapperList());
                return left;
            }));

【讨论】:

    猜你喜欢
    • 2019-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多