【问题标题】:Use the stream to collect on the map by the fields of the object使用流按对象的字段在地图上收集
【发布时间】:2020-11-25 22:28:36
【问题描述】:

假设我有一个这样的对象:

public class Person {
private String name;
private String surName;
private Set <String> domain;

创建这些对象的列表

List<Person> persons = List.of(new Person(...), new Person(...))

如何通过 Stream API 制作这个方法

public Map<String, List<Person>> getDomainsWithPersons(List<Person> persons) {
    Map<String, List<Person>> domainsWithPersons = new HashMap<>();
    for (Person person : persons) {
        for (String domain : person.getDomains()) {
            domainsWithPersons.computeIfAbsent(domain, p -> new ArrayList<>())
                    .add(person);
        }
    }
    return domainsWithPersons;
}

因此该方法只返回一个流,例如:

public Map<String, List<Person>> getDomainsWithPersons(List<Person> persons) {
        return persons.stream()...
    }

【问题讨论】:

  • Person1, Person2 是名字,不是姓氏。对吗?
  • 只是 Person 对象
  • 例如,如果您有List.of(new Person("Person1","Surname1", Set.of("gmail","microsoft")), new Person("Person2","Surname1", Set.of("gmail","ebay")),new Person("Person2","Surname3", Set.of("paypal","ibm")), new Person("Person1","Surname2", Set.of("intel","microsoft")));,您希望如何分组?
  • 类似这样,但使用 StreamAPi Map&lt;String, List&lt;Person&gt;&gt; personsByDomains = new Map&lt;&gt;(); for (Person person : persons) { for (String email : person.getEmails()) { // sets are iterable, we can just do this personsByDomain.putIfAbsent(domain, new ArrayList&lt;Person&gt;()); personsByDomain.get(domain).add(person); } }

标签: java java-stream


【解决方案1】:

Java 没有使用函数式编程范式来做这种事情的好方法——或者,至少,我认为没有。

因此,我们可以使用旧的原型方法 - 遍历 Person 对象,然后根据每个电子邮件地址的域将其添加到 personsByDomain 中的适当列表中。

Map<String, List<Person>> personsByDomains = new Map<>();
for (Person person : persons) {
    for (String email : person.getEmails()) {  // sets are iterable, we can just do this
        String domain = email.substring(email.lastIndexOf('@') + 1);
        personsByDomain.putIfAbsent(domain, new ArrayList<Person>());
        personsByDomain.get(domain).add(person);
    }
}

【讨论】:

  • 如何使用 Stream API?无需格式化域列表)只需分组
【解决方案2】:

你想要的并不那么容易。

我有一个答案,但是,你可能会等待专家的答案。

对于一个人拥有的每封电子邮件,我正在创建一个新的人对象,只是为了放置一封电子邮件。这不是最好的解决方案

public class Teste {

    private static class Person {
        String name;
        String surName;
        Set<String> emails;

        public Person(String name, String surName, Set<String> emails) {
            this.name = name;
            this.surName = surName;
            this.emails = emails;
        }

        @Override
        public String toString() {
            return String.format("Name: %s, Surname: %s, emails: %s", name, surName, emails.toString());
        }
    }


    public static void main(String[] args) {

        List<Person> people = List.of(
                new Person("Matheus", "Rambo", Set.of("matheus@gmail.com", "matheus@outlook.com")),
                new Person("Felipe", "Esteves", Set.of("felipe@proton.mail.com", "felipeesteves@gmail.com"))
        );

        people
                .stream()
                .flatMap(person -> {
                    return person.emails.stream().map(p -> {
                        return new Person(person.name, person.surName, Set.of(p));
                    });
                }).collect(Collectors.groupingBy(x -> {
            final String email = (String) x.emails.toArray()[0];
            return email.substring(email.indexOf("@"));
        }))
                .forEach((key, value) -> {
                    System.out.printf("Domain: %s, people: %s.\n", key, value.toString());
                });
    }
}

这是输出

Domain: @gmail.com, people: [Name: Matheus, Surname: Rambo, emails: [matheus@gmail.com], Name: Felipe, Surname: Esteves, emails: [felipeesteves@gmail.com]].
Domain: @proton.mail.com, people: [Name: Felipe, Surname: Esteves, emails: [felipe@proton.mail.com]].
Domain: @outlook.com, people: [Name: Matheus, Surname: Rambo, emails: [matheus@outlook.com]].

【讨论】:

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