Java8流与地图?

时间:2019-05-29 12:03:30

标签: java dictionary collections java-8 java-stream

我有以下Map(每个键是一个String,每个值是一个List<Message>

我的map是这样的:

1st entry :"MONDAY" -> [message1, message2, message3]
2nd entry : "TUESDAY" -> [message4, message5]
...

我的目标是更改每条消息的内容:

我在想这个:

map.entrySet().stream().peek(entry -> {
    entry.getValue().stream().peek(m -> m.setMessage(changeMessage()))
})

但是不知道如何正确完成它。

3 个答案:

答案 0 :(得分:2)

不幸的是,在不违反原则的情况下,Side-effects并没有提供一种直接更改Map值的方法:

  

通常不鼓励流操作的行为参数产生副作用,因为它们经常会导致无意识地违反无状态要求以及其他线程安全危害。

这是一个可能的解决方案:

Map<String, List<Message>> = map.entrySet().stream()
    .map(e -> {                                                      // iterate entries
            e.setValue(e.getValue().stream()                         // set a new value
                .map(message -> {
                    message  -> message.setMessage(changeMessage()); // .. update message
                    return message;})                                // .. use it
                .collect(Collectors.toList()));                      // return as a List
            return e;})                                              // return an updated value
    .collect(Collectors.toMap(Entry::getKey, Entry::getValue));      // collec to a Map

但是,Java提供了众所周知的for-each功能,可以更直接,更易读的方式实现您的目标:

for (List<Message> list: map.values()) { 
    for (Message message: list) { 
        message.setMessage(changeMessage()); 
    } 
}

答案 1 :(得分:0)

迭代地图,再次更改列表的每个元素,将收集的列表放在地图的同一键上。

map.forEach((k,v)->{
                map.put(k, v.stream().map(i->i+"-changed").collect(Collectors.toList()));

            });

答案 2 :(得分:0)

如果您只想更新所有消息的message,则无需使用整个条目集。您可以仅传输地图的值并映射项目。使用forEach()更新它们:

map.values().stream().flatMap(List::stream)
        .forEach(m -> m.setMessage(changeMessage(m.getMessage())));

如果您需要更改消息的密钥,可以使用以下方法:

map.forEach((key, messages) -> messages.forEach(m -> 
        m.setMessage(changeMessage(key, m.getMessage()))));