【问题标题】:how to merge two streams and return list with different type?如何合并两个流并返回不同类型的列表?
【发布时间】:2017-04-21 03:27:24
【问题描述】:

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

Map<String, List<String>> citiesByZip = new HashMap<>();

持有这些数据

Alameda [95246, 95247]
Colusa [95987]

人员名单

  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<>();

持有这些数据的人

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

我想将列表中的每个人映射到县的 hashmap 以查找居住在哪个县的人

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

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

Junior Jane 20000 Alameda
Junior Jane 30000 Alameda
Joseph James 50000 Alameda
           .
           .
           etc

我知道我可以在 Java 7 中使用传统循环来完成这项工作,但我想知道我是否可以在 Java 8 中使用 stream and lambda 做同样的事情

【问题讨论】:

  • 给我们(可编译的)样本数据来处理。
  • 我认为您需要一张地图,其键是邮政编码,其值是与该邮政编码相关的城市。
  • @Alexander 完全正确,但我不知道如何在其他流中引用流
  • 给我们(可编译的)样本数据来处理。
  • @kero 在不相关的说明中,您的citiesByZip 地图实际上更像zipsByCity(邮政编码是按城市查找的,而不是您的名字所暗示的其他方式)。另外,请查看来自 Google 的 Guava 库的 Multimap。它非常适合您的用例(为每个城市键映射多个邮政编码值)。有一些方法可以“反转”多张地图,可以在给定zipsByCity 的情况下生成citiesByZip 地图

标签: java-8 java-stream


【解决方案1】:

首先,您需要一个数据结构来高效查找特定邮政编码,因为Map&lt;String, List&lt;String&gt;&gt; 不适合这种情况。你可以像这样转换它

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));

或者,您可以使用

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);

它不需要临时的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;
    }
}

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

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

不过,改用委托可能会有好处:

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;
    }
}

 

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

【讨论】:

    猜你喜欢
    • 2016-08-05
    • 1970-01-01
    • 2019-06-09
    • 1970-01-01
    • 1970-01-01
    • 2020-05-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多