代码之家  ›  专栏  ›  技术社区  ›  jjones

Java 8 Lambda创建一个映射,其中Value是列表的包装对象

  •  2
  • jjones  · 技术社区  · 8 年前

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

    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(这是一个地址列表)

    1 回复  |  直到 8 年前
        1
  •  2
  •   Ousmane D.    8 年前

    一种方法是根据 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<Address> 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;
                }));