使用 java 8 流 API 将一张地图转换成另一张地图
Converting a map into another map using the java 8 stream API
假设我有以下地图:
Map<Member, List<Message>> messages = ... //constructed somehow
我想使用 java 8 流 api 以获得:
SortedMap<Message, Member> latestMessages = ...
传递到 SortedMap/TreeMap 的比较器将基于消息发送日期字段。
此外,在已发送消息列表中,我会 select 最新的消息,这将成为排序映射的关键。
我怎样才能做到这一点?
编辑 1:
Comparator<Message> bySendDate = Comparator.comparing(Message::getSendDate);
SortedMap<Message, Member> latestMessages = third.entrySet().stream()
.collect(Collectors.toMap(e -> e.getValue().stream().max(bySendDate).get(), Map.Entry::getKey, (x, y) -> {
throw new AssertionError();
}, () -> new TreeMap(bySendDate.thenComparing(Comparator.comparing(Message::getId)))));
我得到以下编译错误:
The method collect(Collector<? super T,A,R>) in the type Stream<T> is not applicable for the arguments (Collector<Map.Entry<Member,List<Message>>,?,TreeMap>)
让我们把它分成两部分。
首先,通过减少特定通信伙伴(Member
)的最新消息,将Map<Member, List<Message>> messages
转换为Map<Message, Member> latestMessages
:
Map<Message, Member> latestMessages0 = messages.entrySet().stream()
.collect(Collectors.toMap(
e -> e.getValue().stream().max(Comparator.comparing(Message::getSendDate)).get(),
Map.Entry::getKey));
此处,生成的 map
未排序,但每个映射都将包含与该参与者共享的最新消息。
其次,如果您希望生成的地图按 sendDate 排序,您必须添加另一个次要排序标准以避免丢失恰好具有相同日期的 Messages
。假设您有一个唯一的 Long
ID,将此 ID 添加为具有相同日期的邮件的次要排序标准就足够了:
Comparator<Message> bySendDate=Comparator.comparing(Message::getSendDate);
SortedMap<Message, Member> latestMessages = messages.entrySet().stream()
.collect(Collectors.toMap(
e -> e.getValue().stream().max(bySendDate).get(),
Map.Entry::getKey, (x,y) -> {throw new AssertionError();},
()->new TreeMap<>(bySendDate.thenComparing(Comparator.comparing(Message::getId)))));
由于按唯一 ID 排序应该可以解决任何歧义,我提供了一个合并函数,它将无条件抛出,因为永远不需要调用它。
假设我有以下地图:
Map<Member, List<Message>> messages = ... //constructed somehow
我想使用 java 8 流 api 以获得:
SortedMap<Message, Member> latestMessages = ...
传递到 SortedMap/TreeMap 的比较器将基于消息发送日期字段。
此外,在已发送消息列表中,我会 select 最新的消息,这将成为排序映射的关键。
我怎样才能做到这一点?
编辑 1:
Comparator<Message> bySendDate = Comparator.comparing(Message::getSendDate);
SortedMap<Message, Member> latestMessages = third.entrySet().stream()
.collect(Collectors.toMap(e -> e.getValue().stream().max(bySendDate).get(), Map.Entry::getKey, (x, y) -> {
throw new AssertionError();
}, () -> new TreeMap(bySendDate.thenComparing(Comparator.comparing(Message::getId)))));
我得到以下编译错误:
The method collect(Collector<? super T,A,R>) in the type Stream<T> is not applicable for the arguments (Collector<Map.Entry<Member,List<Message>>,?,TreeMap>)
让我们把它分成两部分。
首先,通过减少特定通信伙伴(Member
)的最新消息,将Map<Member, List<Message>> messages
转换为Map<Message, Member> latestMessages
:
Map<Message, Member> latestMessages0 = messages.entrySet().stream()
.collect(Collectors.toMap(
e -> e.getValue().stream().max(Comparator.comparing(Message::getSendDate)).get(),
Map.Entry::getKey));
此处,生成的 map
未排序,但每个映射都将包含与该参与者共享的最新消息。
其次,如果您希望生成的地图按 sendDate 排序,您必须添加另一个次要排序标准以避免丢失恰好具有相同日期的 Messages
。假设您有一个唯一的 Long
ID,将此 ID 添加为具有相同日期的邮件的次要排序标准就足够了:
Comparator<Message> bySendDate=Comparator.comparing(Message::getSendDate);
SortedMap<Message, Member> latestMessages = messages.entrySet().stream()
.collect(Collectors.toMap(
e -> e.getValue().stream().max(bySendDate).get(),
Map.Entry::getKey, (x,y) -> {throw new AssertionError();},
()->new TreeMap<>(bySendDate.thenComparing(Comparator.comparing(Message::getId)))));
由于按唯一 ID 排序应该可以解决任何歧义,我提供了一个合并函数,它将无条件抛出,因为永远不需要调用它。