【问题标题】:Converting a map into another map using the java 8 stream API使用 java 8 流 API 将地图转换为另一个地图
【发布时间】:2015-03-02 16:12:05
【问题描述】:

假设我有以下地图:

Map<Member, List<Message>> messages = ... //constructed somehow

我想使用 java 8 流 api 来获得:

SortedMap<Message, Member> latestMessages = ...

传入 SortedMap/TreeMap 的比较器将基于消息 sendDate 字段。

此外,在已发送消息列表中,我会选择最新的消息,这将成为排序映射的关键。

我怎样才能做到这一点?

编辑 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>)

【问题讨论】:

  • 您确定要这个吗?这意味着只有一个Message 和一个特定的sendDate,即使存在具有相同日期但发送者和接收者不同的不同消息。
  • 是的。基本上,我会收到给定成员发送或接收的最新消息。
  • 我实际上是在实现一个消息框,例如 what'sapp 或 hangout 上的消息框等...
  • 哦,我现在和你在一起!你是对的。让我编辑我的问题....
  • @Holger 我认为这与这个问题相同:stackoverflow.com/questions/28810301/… 我想出了一些办法;但也许你有更好的实现(起初我并不清楚这个问题)。 ;-)

标签: dictionary java-8 java-stream


【解决方案1】:

让我们把它分解成两部分。

首先,通过将特定通信伙伴 (Member) 的消息减少 到最新,将 Map&lt;Member, List&lt;Message&gt;&gt; messages 转换为 Map&lt;Message, Member&gt; 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 排序应该可以解决任何歧义,因此我提供了一个合并函数,该函数将无条件抛出,因为永远不需要调用它。

【讨论】:

  • 非常感谢。但是我遇到了上述错误......我已经相应地编辑了我的帖子。
  • 您使用哪个编译器?请注意new TreeMap(…) 应该是new TreeMap&lt;&gt;(…),我忘记了这个&lt;&gt; 的东西,但我的编译器只产生警告(并且只产生-Xlint)但也许你的编译器更挑剔......
  • 正是我今天需要的 ;-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-16
  • 2012-11-30
  • 2016-07-28
  • 1970-01-01
  • 2018-02-22
相关资源
最近更新 更多