[英]Java Stream sortingBy and filter()
I have a specific question about Java 8 streams.我有一个关于 Java 8 流的具体问题。 I could not find anything that was close to the solution of my problem even it sounds not too complicated.即使听起来不太复杂,我也找不到任何接近解决问题的方法。
I want to convert a List<Person>
into a Map<Company, List<Person>>
.我想将List<Person>
转换为Map<Company, List<Person>>
。 The Company is an enum.该公司是一个枚举。 Now the Map
should be grouped by the Company
(so far I got everything working. After I want to filter all the List<Person>
of the Map
by an attribute : the Name of the Person
. I only want to have the Person(s) with the longest name inside. Example:现在Map
应该由进行分组Company
(到目前为止我得到的一切工作后,我想过滤所有的。 List<Person>
的的Map
的属性:在的名称Person
。我只是想有个人(S ) 里面有最长的名字。例如:
This is what I got so far:这是我到目前为止得到的:
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
public class PersonMap {
public static void main(String[] args) {
Person person1 = new Person("Pete", Company.APPLE);
Person person2 = new Person("Joe", Company.APPLE);
Person person3 = new Person("Jack", Company.APPLE);
Person person4 = new Person("Robert", Company.MICROSOFT);
Person person5 = new Person("Cate", Company.MICROSOFT);
Person person6 = new Person("Abi", Company.MICROSOFT);
List<Person> list = new LinkedList<>();
list.add(person1);
list.add(person2);
list.add(person3);
list.add(person4);
list.add(person5);
list.add(person6);
}
public Map<Company, List<Person>> groupPersonByCompanyAndFilterByName (List <Person> list){
Map<Company, List<Person>> outputMap =
list.stream().collect(Collectors.groupingBy(Person::getCompany))
.entrySet().stream()
.filter(p -> p.getValue().stream().toString().length() !=
p.getValue().stream().map(Person::getName).mapToInt(String::length).max().getAsInt())
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
return outputMap;
}
}
The filter function is not working here.过滤功能在这里不起作用。 The output I want is:我想要的输出是:
{MICROSOFT=["person4"], APPLE=[person1, person3]}
Does anybody have good knowledge and can help me please!有没有人有很好的知识,可以帮助我吗!
Here is an approach using teeing这是一种使用开球的方法
public Map<Company, List<Person>> groupPersonByCompanyAndFilterByName (List <Person> list){
return list.stream().collect(groupingBy(Person::getCompany,
teeing(
mapping(Person::getName, maxBy(Comparator.comparing(String::length))),
toList(),
(a, b) -> b.stream().filter(x -> x.getName().length() == a.get().length())
.collect(toList())
)
));
}
For better performance, you shouldn't do it in a single stream chain.为了获得更好的性能,您不应在单个流链中执行此操作。
Try this instead:试试这个:
List<Person> list = new LinkedList<>();
list.add(new Person("Pete", Company.APPLE));
list.add(new Person("Joe", Company.APPLE));
list.add(new Person("Jack", Company.APPLE));
list.add(new Person("Robert", Company.MICROSOFT));
list.add(new Person("Cate", Company.MICROSOFT));
list.add(new Person("Abi", Company.MICROSOFT));
Map<Company, List<Person>> map = list.stream().collect(Collectors.groupingBy(Person::getCompany));
map.values().forEach(persons -> {
int maxLen = persons.stream().mapToInt(p -> p.getName().length()).max().getAsInt();
persons.removeIf(p -> p.getName().length() != maxLen);
});
System.out.println(map);
Output输出
{APPLE=[Pete, Jack], MICROSOFT=[Robert]}
For the above code, I used the following extra classes:对于上面的代码,我使用了以下额外的类:
enum Company {
APPLE, MICROSOFT
}
class Person {
private final String name;
private final Company company;
public Person(String name, Company company) {
this.name = name;
this.company = company;
}
public String getName() {
return this.name;
}
public Company getCompany() {
return this.company;
}
@Override
public String toString() {
return this.name;
}
}
You can do it grouping by on multiple fields Company
and length of name
您可以在多个字段Company
和name
长度上进行分组
Map<Company, Map<Integer, List<Person>>> map = list.stream()
.collect(Collectors.groupingBy(Person::getCompany, Collectors.groupingBy(p -> p.getName().length())));
And the create Entries
from outer map key
and inner map value
having max length (name) which is inner map key
并且从外部映射key
和内部映射value
创建Entries
,其最大长度(名称)是内部映射key
Map<Company, List<Person>> resultMap = map.entrySet().stream()
.map(e -> new AbstractMap.SimpleEntry<>(e.getKey(),
e.getValue().entrySet().stream()
.max(Comparator.comparing(Map.Entry<Integer, List<Person>>::getKey)).get().getValue()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
You can combine these two operations into single stream also您也可以将这两个操作组合成单个流
Person person1 = new Person("Pete", "APPLE");
Person person2 = new Person("Joe", "APPLE");
Person person3 = new Person("Jack", "APPLE");
Person person4 = new Person("Robert", "MICROSOFT");
Person person5 = new Person("Cate", "MICROSOFT");
Person person6 = new Person("Abi", "MICROSOFT");
List<Person> list = new ArrayList<>();
list.add(person1);
list.add(person2);
list.add(person3);
list.add(person4);
list.add(person5);
list.add(person6);
//Adapt your structure and with this function you can group
Map<String, List<Person>> map = list.stream().collect(Collectors.groupingBy(person -> person.getCompany()));
for (String name: map.keySet()){
List<Person> persons = map.get(name);
System.out.println("[" + name + "]");
persons.forEach(s -> System.out.println(s.getName()));
}
Out Log: [APPLE] Pete Joe Jack [MICROSOFT] Robert Cate Abi退出日志:[APPLE] 皮特·乔·杰克 [MICROSOFT] 罗伯特·凯特·阿比
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.