Java 流 sortingBy 和 filter()
Java Stream sortingBy and filter()
我有一个关于 Java 8 个流的具体问题。我找不到任何接近我的问题的解决方案,即使它听起来不太复杂。
我想将 List<Person>
转换为 Map<Company, List<Person>>
。公司是一个枚举。现在 Map
应该按 Company
分组(到目前为止我一切正常。在我想通过属性过滤 Map
的所有 List<Person>
之后:名称Person
的。我只想要里面名字最长的人。示例:
这是我目前得到的:
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;
}
}
过滤功能在这里不起作用。我想要的输出是:
{MICROSOFT=["person4"], APPLE=[person1, person3]}
请问有哪位大神可以帮帮我!
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()));
}
输出日志:
[苹果]
皮特
乔
杰克
[微软]
罗伯特
美食
阿比
为了获得更好的性能,您不应在单个流链中执行此操作。
试试这个:
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);
输出
{APPLE=[Pete, Jack], MICROSOFT=[Robert]}
对于上面的代码,我使用了以下额外的类:
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;
}
}
这是一种使用发球台的方法
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())
)
));
}
您可以根据多个字段 Company
和 name
的长度进行分组
Map<Company, Map<Integer, List<Person>>> map = list.stream()
.collect(Collectors.groupingBy(Person::getCompany, Collectors.groupingBy(p -> p.getName().length())));
并且从外部映射 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));
您也可以将这两个操作组合成一个流
我有一个关于 Java 8 个流的具体问题。我找不到任何接近我的问题的解决方案,即使它听起来不太复杂。
我想将 List<Person>
转换为 Map<Company, List<Person>>
。公司是一个枚举。现在 Map
应该按 Company
分组(到目前为止我一切正常。在我想通过属性过滤 Map
的所有 List<Person>
之后:名称Person
的。我只想要里面名字最长的人。示例:
这是我目前得到的:
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;
}
}
过滤功能在这里不起作用。我想要的输出是:
{MICROSOFT=["person4"], APPLE=[person1, person3]}
请问有哪位大神可以帮帮我!
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()));
}
输出日志: [苹果] 皮特 乔 杰克 [微软] 罗伯特 美食 阿比
为了获得更好的性能,您不应在单个流链中执行此操作。
试试这个:
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);
输出
{APPLE=[Pete, Jack], MICROSOFT=[Robert]}
对于上面的代码,我使用了以下额外的类:
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;
}
}
这是一种使用发球台的方法
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())
)
));
}
您可以根据多个字段 Company
和 name
Map<Company, Map<Integer, List<Person>>> map = list.stream()
.collect(Collectors.groupingBy(Person::getCompany, Collectors.groupingBy(p -> p.getName().length())));
并且从外部映射 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));
您也可以将这两个操作组合成一个流