Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Java Streams按集合属性分组_Java_Java 8_Java Stream - Fatal编程技术网

使用Java Streams按集合属性分组

使用Java Streams按集合属性分组,java,java-8,java-stream,Java,Java 8,Java Stream,我有一个包含字符串集合的对象,比如说一个人所说的语言 public class Person { private String name; private int age; private List<String> languagesSpoken; // ... } 当然,这可以通过命令式方式轻松编程,但是如何使用Java流以功能性方式编程呢?我尝试过类似于people.stream.collect(groupingBy(Person::getLangua

我有一个包含字符串集合的对象,比如说一个人所说的语言

public class Person {
   private String name;
   private int age;
   private List<String> languagesSpoken;

   // ...
}

当然,这可以通过命令式方式轻松编程,但是如何使用Java流以功能性方式编程呢?我尝试过类似于
people.stream.collect(groupingBy(Person::getLanguagesSpoken))
的方法,但这当然给了我一个
映射。我能找到的所有示例都在原语或字符串上使用了
groupingBy

您可以将
Person
实例分成两组语言和
Person
(使用
flatMap
),然后根据需要进行分组:

Map<String, List<Person>> langPersons =
    people.stream()
          .flatMap(p -> p.getLanguagesSpoken()
                         .stream()
                         .map(l -> new SimpleEntry<>(l,p)))
          .collect(Collectors.groupingBy(Map.Entry::getKey,
                                         Collectors.mapping(Map.Entry::getValue,
                                                            Collectors.toList())));
Map-langperson=
people.stream()
.flatMap(p->p.getLanguagesSpoken()
.stream()
.map(l->new SimpleEntry(l,p)))
.collect(Collectors.groupingBy(Map.Entry::getKey、,
Collectors.mapping(Map.Entry::getValue,
收藏家;

这在不使用流的情况下也是可行的,仍然使用java-8的新特性

people.forEach(x -> {
        x.getLanguagesSpoken().forEach(lang -> {
            langPersons.computeIfAbsent(lang, ignoreMe -> new ArrayList<>()).add(x);
        });
});
people.forEach(x->{
x、 getLanguagesSpoken().forEach(lang->{
langPersons.computeIfAbsent(lang,ignoreMe->newArrayList()).add(x);
});
});

由于您想“从功能上”思考,您可以从思考group by的属性开始。groupby最多只能生成与输入相同数量的元素(如果它们都在不同的“类”中)。在你的例子中,语言的数量很容易超过人的数量(事实上,你的例子就是这样)。因此,无论您给
groupingBy
收集器提供什么参数,您都需要对
列表
执行一些操作,使其至少具有与所说语言数相等的元素数。一种可能性是Eran的答案。添加了Streams和Lambda表达式是为了可读性,对吗?(顺便说一句,我并不反对你的完美答案,只是对Streams和Lambda表达式本身的评论。)
Map<String, List<Person>> langPersons =
    people.stream()
          .flatMap(p -> p.getLanguagesSpoken()
                         .stream()
                         .map(l -> new SimpleEntry<>(l,p)))
          .collect(Collectors.groupingBy(Map.Entry::getKey,
                                         Collectors.mapping(Map.Entry::getValue,
                                                            Collectors.toList())));
people.forEach(x -> {
        x.getLanguagesSpoken().forEach(lang -> {
            langPersons.computeIfAbsent(lang, ignoreMe -> new ArrayList<>()).add(x);
        });
});