使用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);
});
});