我写了这个lambda,它从包含在枚举<Code, Message>
中的映射MessageKeyRegistry
获取值,并创建添加到另一个映射中,其中Code为键,而MessageKeyRegistry
为值。
Map<MessageKey, MessageKeyRegistry> keyMap = new HashMap<>();
EnumSet.allOf(MessageKeyRegistry.class)
.forEach(messageKeyRegistry -> messageKeyRegistry.getCodeToMessage().keySet()
.forEach(code -> keyMap.put(code, messageKeyRegistry)));
现在,我想满足函数式编程的不变性概念,并编写一个直接返回不可变映射的lambda。
最佳答案
我已经写了这个lambda。
您不仅编写了lambda,还编写了使用lambda表达式的方法链。如果它们是code -> keyMap.put(code, messageKeyRegistry)
,则为1。
回到您的问题。您正确地开始了迭代(从EnumSet
开始),下一步是了解forEach
方法中发生的事情。
使用messageKeyRegistry
从一组键中提取代码,并将它们用作键
将提取器用作值messageKeyRegistry
。
这是map
的工作,但是由于数据结构更复杂(集合中的集合),因此flatMap
会更好。最后,您将得到如下结果:
Map<MessageKey, MessageKeyRegistry> keyMap = EnumSet.allOf(MessageKeyRegistry.class)
.stream()
.flatMap(messageKeyRegistry -> messageKeyRegistry.getCodeToMessage().keySet()
.stream()
.map(code -> new AbstractMap.SimpleEntry<>(code, messageKeyRegistry)))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
但是,您所做的事情有一个缺点。我看到密钥被覆盖了,因为不能有从原始解决方案中可见的重复项,即从该行重复至少一次,这表明密钥可能被覆盖了:
.forEach(code -> keyMap.put(code, messageKeyRegistry))
所以我建议的是使用
Collectors.groupingBy
进行组映射:Map<MessageKey, List<MessageKeyRegistry>> keyMap = EnumSet.allOf(MessageKeyRegistry.class)
.stream()
.flatMap(messageKeyRegistry -> messageKeyRegistry.getCodeToMessage().keySet()
.stream()
.map(code -> new AbstractMap.SimpleEntry<>(code, messageKeyRegistry)))
.collect(Collectors.groupingBy(Entry::getKey));
对于不可变映射,如果您表示的是只读映射,请使用
Map<MessageKey, List<MessageKeyRegistry>>
包装器:Map<MessageKey, List<MessageKeyRegistry>> unmodifiableKeyMap = Collections.unmodifiableMap(keyMap);