如何合并两个流并返回不同类型的列表?

ker*_*ero 3 java-8 java-stream

我有两个流,我想将它们组合成不同的列表,即我有哈希映射

Map<String, List<String>> citiesByZip = new HashMap<>();
Run Code Online (Sandbox Code Playgroud)

持有这些数据

Alameda [95246, 95247]
Colusa [95987]
Run Code Online (Sandbox Code Playgroud)

人员名单

  class Person {
    private String firstName;
    private String lastName;
    private int income;
    private int zipCode;



 People(String firstName, String lastName, int income, int zipCode) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.income = income;
        this.zipCode = zipCode;
    }

    public String getFirstName() {
        return firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public int getIncome() {
        return income;
    }
    public int getZipCode() {
        return zipCode;
    }
}
 List<Person> persons= new ArrayList<>();
Run Code Online (Sandbox Code Playgroud)

持有这些数据

Junior Jane 20000 95246
Junior Jane 30000 95246
Joseph James 50000 95247
Patricia Allen 60000 95247
Opal Campbell 70000 95987
Dorothy Rook 80004 95987
Mary Nelson 80000 23666
Run Code Online (Sandbox Code Playgroud)

我想将列表中的每个人映射到县的哈希映射,以查找哪个县居民

List <FinalObject> finalObjects= new  ArrayList<>();
finalObjects = Stream.concat(peopleStream.stream(), citiesByZip.entrySet().stream())
                .collect(Collectors.toMap(
                ))
Run Code Online (Sandbox Code Playgroud)

这个列表应该返回这样的最终对象列表

Junior Jane 20000 Alameda
Junior Jane 30000 Alameda
Joseph James 50000 Alameda
           .
           .
           etc
Run Code Online (Sandbox Code Playgroud)

我知道我可以在传统循环的Java 7中完成这项工作,但我想知道我是否可以在java 8中使用相同的东西 stream and lambda

Hol*_*ger 6

首先,您需要一个数据结构来有效地查找特定的邮政编码,因为Map<String, List<String>>它不适合.你可以转换它

Map<Integer,String> zipToCity = citiesByZip.entrySet().stream()
    .flatMap(e -> e.getValue().stream().map(Integer::valueOf)
                   .map(zip -> new AbstractMap.SimpleEntry<>(zip, e.getKey())))
    .collect(Collectors.toMap(Entry::getKey, Entry::getValue));
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用

Map<Integer,String> zipToCity = citiesByZip.entrySet().stream()
    .collect(HashMap::new,
            (m,e) -> e.getValue().forEach(zip -> m.put(Integer.valueOf(zip), e.getKey())),
            Map::putAll);
Run Code Online (Sandbox Code Playgroud)

它不需要临时AbstractMap.SimpleEntry实例,但看起来很像传统的迭代解决方案.事实上,对于顺序用例,循环实际上更简单.

然后,您可以使用单个流操作将Person实例转换为实例FinalObject.由于你没有指定FinalObject类,我假设

class FinalObject {
    private String firstName, lastName, city;
    private int income;
    FinalObject(String firstName, String lastName, int income, String city) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.income = income;
        this.city = city;
    }

    public String getFirstName() {
        return firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public int getIncome() {
        return income;
    }
    public String getCity() {
        return city;
    }
    @Override public String toString() {
        return firstName+" "+lastName+" "+income+" "+city;
    }
}
Run Code Online (Sandbox Code Playgroud)

使用此定义,您可以使用zip查找进行转换

List<FinalObject> finalObjects = persons.stream()
    .map(p -> new FinalObject(p.getFirstName(), p.getLastName(),
                  p.getIncome(), zipToCity.getOrDefault(p.getZipCode(), "Unknown")))
    .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

但是,使用委托代替可能是有益的:

class FinalObject {
    private Person p;
    String city;

    FinalObject(Person p, String city) {
        this.p = p;
        this.city = city;
    }

    public String getFirstName() {
        return p.getFirstName();
    }
    public String getLastName() {
        return p.getLastName();
    }
    public int getIncome() {
        return p.getIncome();
    }
    public String getCity() {
        return city;
    }
    @Override public String toString() {
        return getFirstName()+" "+getLastName()+" "+getIncome()+" "+city;
    }
}
Run Code Online (Sandbox Code Playgroud)

 

List<FinalObject> finalObjects = persons.stream()
    .map(p -> new FinalObject(p, zipToCity.getOrDefault(p.getZipCode(), "Unknown")))
    .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)