我有一张<String, List<T>>
的地图,想要为每个条目的值创建一个流,我可以在其中找到List<T>
的最大元素,然后在该地图<String, List<T>>
之后到<String, T>
。我怎么做?花了3个多小时才想出来。
更新
忘了说我被要求做两种方式:用Collector.toMap
而没有它,我对没有它的方式感到最好奇。
我遇到的一步是:
employees.stream()
.flatMap(e -> e.getJobHistory().stream()
.map(j -> new PersonPositionDuration(e.getPerson(), j.getPosition(), j.getDuration())))
.collect(Collectors.groupingBy(p -> p.getPosition()))
.entrySet().
employees
是Employee
对象的列表,每个对象都有jobHistory
属性,也是List
,并且每个条目都有employer
属性,String
。所以我把这个List<Employee>
变成Map<String, List<PersonPositionDuration>>
,其中key是就业者,value是一个类,包含一个人的信息以及他作为这个雇员的人工作了多长时间。钥匙不是唯一的。
我想要做的是找到持续时间最长的PersonPositionDuration
,我们可以通过getDuration()
获取。那么在我获得和输入后我该怎么办?
此外,我建议使用Collectors.maxBy
和Collectors.collectingAndThen
,但我不知道该怎么做。
答案 0 :(得分:3)
假设T
实现Comparable
(因为您需要能够计算两个值的最大值),您可以将代码包装在如下方法中:
public <T extends Comparable<T>> Map<String, T> convert(Map<String, List<T>> data) {
// variable for readability, you can return it right away if you prefer
Map<String, T> result = data.entrySet().stream().collect(Collectors.toMap(
// for each key in our map...
e -> e.getKey(),
// ... we determine the maximum and store it as new value
e -> Collections.max(e.getValue())
));
return result;
}
创建Set<Map.Entry<String, List<T>>>
,您可以使用Stream
使用Map<String, T>
转换值类型,将Collections.max()
转换为Comparable.compareTo
比较两个对象并确定哪个对象大于另一个。请注意,您可以像Integer
或Double
(以及更多)一样使用它,因为它们都会实现Comparable
。
答案 1 :(得分:2)
如果您的map
类型为<String, List<Integer>>
,则可以
Map<String, List<Integer>> map = new HashMap<>();
map.put("a", Arrays.asList(5, 3, 7));
map.put("b", Arrays.asList(1, 5));
map.put("c", Arrays.asList(45, 2));
map.put("d", Arrays.asList(4, 6, 2, 34));
map.entrySet().stream().collect(Collectors.toMap(Entry::getKey, entry -> {
return entry.getValue().stream().max(Integer::compareTo).orElse(0);
}));
输出
{a=7, b=5, c=45, d=34}
您可以使用类型entry.getValue().stream().max(Integer::compareTo).orElse(0)
的比较器或类类型修改T
。
答案 2 :(得分:0)
您想要实现的目标或数据结构的外观并不完全清楚。你写的和你展示的代码不匹配。他们完成了截然不同的事情。
但您希望使用Collectors.maxBy
而不使用Collectors.toMap
来获得解决方案。其他答案没有提供这样的解决方案。因此,我会尝试给一个。
您的数据:
作为您的数据结构,我假设您有雇主,每个雇主雇用多名员工。每个员工都有一些个人信息,他工作/编辑的职位以及他在这个岗位上工作的时间,直到知道为止。
例如(Map employerEmployeeMap ):
CompanyA: [{Max, Developer, 5.4}, {Mari, Designer, 6.8}, {Paul, Manager, 1.2}]
CompanyB: [{Lea, CEO, 7.1}, {Tom, Admin, 4.5}, {Ria, Marketing, 0.4}]
CompanyC: [{Alex, Secretary, 1.5}, {Lisa, Developer, 3.3}, {Mia, Developer, 2.7}]
您想要达到的目标:
您希望PersonPositionDuration
的持续时间最长。我不确定你是否只想要所有雇主或每个雇主的持续时间最长的人。因此,我将提供多种解决方案。
使用maxBy解决方案
如果您只想要持续时间超过所有雇主的人,您可以迭代员工并获得持续时间最长的员工:
Optional<PersonPositionDuration> maxDurationPerson = employerEmployeeMap.values().stream()
.flatMap(List::stream)
.collect(maxBy(comparing(PersonPositionDuration::getDuration)));
这等于:
Optional<PersonPositionDuration> maxDurationPerson = employerEmployeeMap.values().stream()
.flatMap(List::stream)
.max(comparing(PersonPositionDuration::getDuration));
结果:{Lea, CEO, 7.1}
如果您只想要持续时间最长但不想丢失雇主信息的人:
Optional<Pair<String, PersonPositionDuration>> maxDurationPersonCompany = employerEmployeeMap.entrySet().stream()
.flatMap(entry -> entry.getValue().stream().map(p -> new Pair<>(entry.getKey(), p)))
.max(comparing(entry -> entry.getValue().getDuration()));
结果:CompanyB: {Lea, CEO, 7.1}
如果您想要每个公司的持续时间最长的人,您可以执行以下操作:
Map<String, Optional<Pair<String, PersonPositionDuration>>> maxDurationPerCompany = employerEmployeeMap.entrySet().stream()
.flatMap(entry -> entry.getValue().stream().map(p -> new Pair<>(entry.getKey(), p)))
.collect(groupingBy(Pair::getKey, maxBy(comparing(entry -> entry.getValue().getDuration()))));
结果:
CompanyA: {Mari, Designer, 6.8}
CompanyB: {Lea, CEO, 7.1}
Companyc: {Lisa, Developer, 3.3}
我希望这能涵盖您的问题和您的需求。如果没有,如果缺少某些东西或者某些东西不清楚,请随时发表评论。
完整的工作示例:
import javafx.util.*;
import java.util.*;
import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.*;
public class Main {
public static void main(String[] args) {
class PersonPositionDuration {
private final String person;
private final String position;
private final Double duration;
public PersonPositionDuration(String person, String position, Double duration) {
this.person = person;
this.position = position;
this.duration = duration;
}
public Double getDuration() {
return duration;
}
}
Map<String, List<PersonPositionDuration>> employerEmployeeMap = new HashMap<>();
employerEmployeeMap.put("CompanyA", Arrays.asList(new PersonPositionDuration("Max", "Developer", 5.4), new PersonPositionDuration("Mari", "Designer", 6.8), new PersonPositionDuration("Paul", "Manager", 1.2)));
employerEmployeeMap.put("CompanyB", Arrays.asList(new PersonPositionDuration("Lea", "CEO", 7.1), new PersonPositionDuration("Tom", "Admin", 4.5), new PersonPositionDuration("Ria", "Marketing", 0.4)));
employerEmployeeMap.put("CompanyC", Arrays.asList(new PersonPositionDuration("Alex", "Secretary", 1.5), new PersonPositionDuration("Lisa", "Developer", 3.3), new PersonPositionDuration("Mia", "Developer", 2.7)));
Optional<PersonPositionDuration> maxDurationPerson = employerEmployeeMap.values()
.stream()
.flatMap(List::stream)
.max(comparing(PersonPositionDuration::getDuration));
Optional<Pair<String, PersonPositionDuration>> maxDurationPersonCompany = employerEmployeeMap.entrySet()
.stream()
.flatMap(entry -> entry.getValue()
.stream()
.map(p -> new Pair<>(entry.getKey(), p)))
.max(comparing(entry -> entry.getValue()
.getDuration()));
Map<String, Optional<Pair<String, PersonPositionDuration>>> maxDurationPerCompany = employerEmployeeMap.entrySet()
.stream()
.flatMap(entry -> entry.getValue()
.stream()
.map(p -> new Pair<>(entry.getKey(), p)))
.collect(groupingBy(Pair::getKey, maxBy(comparing(entry -> entry.getValue()
.getDuration()))));
}
}