我写了这个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);

09-27 09:21