sta*_*ack 0 java collections java-8 maxby java-stream
假设我们有一个包含字段的 person 类:
Class Person {
private String name;
private Integer id (this one is unique);
}
Run Code Online (Sandbox Code Playgroud)
然后我们有一个List<Person> people
这样的:
['Jerry', 993]
['Tom', 3]
['Neal', 443]
['Jerry', 112]
['Shannon', 259]
['Shannon', 533]
Run Code Online (Sandbox Code Playgroud)
我怎样才能创建一个新List<Person> uniqueNames
的,使其仅过滤唯一名称并保留该名称的最高 ID。
所以最终列表将如下所示:
['Jerry', 993]
['Tom', 3]
['Neal', 443]
['Shannon', 533]
Run Code Online (Sandbox Code Playgroud)
Collectors.groupingBy
+Collectors.maxBy
应该能够构建按姓名分组的人员地图,然后选择最大值:
List<Person> persons = Arrays.asList(
new Person("Jerry", 123),
new Person("Tom", 234),
new Person("Jerry", 456),
new Person("Jake", 789)
);
List<Person> maxById = persons
.stream()
.collect(Collectors.groupingBy(
Person::getName,
Collectors.maxBy(Comparator.comparingInt(Person::getID))
))
.values() // Collection<Optional<Person>>
.stream() // Stream<Optional<Person>>
.map(opt -> opt.orElse(null))
.collect(Collectors.toList());
System.out.println(maxById);
Run Code Online (Sandbox Code Playgroud)
输出:
[789: Jake, 234: Tom, 456: Jerry]
Run Code Online (Sandbox Code Playgroud)
更新
有没有办法获得因在该stream()中重复而被删除的Person对象的单独列表?
最好将分组的项目收集在一个列表中,然后在某个包装类中进行转换,提供有关人员maxById
和已删除重复人员的列表的信息:
class PersonList {
private final Person max;
private final List<Person> deduped;
public PersonList(List<Person> group) {
this.max = Collections.max(group, Comparator.comparingInt(Person::getID));
this.deduped = new ArrayList<>(group);
this.deduped.removeIf(p -> p.getID() == max.getID());
}
@Override
public String toString() {
return "{max: " + max + "; deduped: " + deduped + "}";
}
}
Run Code Online (Sandbox Code Playgroud)
那么这些人应该像这样收集:
List<PersonList> maxByIdDetails = new ArrayList<>(persons
.stream()
.collect(Collectors.groupingBy(
Person::getName,
LinkedHashMap::new,
Collectors.collectingAndThen(
Collectors.toList(), PersonList::new
)
))
.values()); // Collection<PersonList>
maxByIdDetails.forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)
输出:
{max: 456: Jerry; deduped: [123: Jerry]}
{max: 234: Tom; deduped: []}
{max: 789: Jake; deduped: []}
Run Code Online (Sandbox Code Playgroud)
更新2
获取重复人员列表:
{max: 456: Jerry; deduped: [123: Jerry]}
{max: 234: Tom; deduped: []}
{max: 789: Jake; deduped: []}
Run Code Online (Sandbox Code Playgroud)
输出:
[123: Jerry]
Run Code Online (Sandbox Code Playgroud)
其中removeMax
可以这样实现:
List<Person> duplicates = persons
.stream()
.collect(Collectors.groupingBy(Person::getName))
.values() // Collection<List<Person>>
.stream() // Stream<List<Person>>
.map(MyClass::removeMax)
.flatMap(List::stream) // Stream<Person>
.collect(Collectors.toList()); // List<Person>
System.out.println(duplicates);
Run Code Online (Sandbox Code Playgroud)
或者,如果hashCode
和equals
在类 中正确实现Person
,则可以使用以下方法计算两个列表之间的差异removeAll
:
[123: Jerry]
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2232 次 |
最近记录: |