当我们在Java中将映射的键转换为小写时,有什么简单的方法可以合并值集吗?

Is there any simple way to merge value set when we convert key of map to lower case in Java?

我有一张混合大小写的地图,例如

{a=[v1, V1], A={v2, V2, v3} 

我想把所有东西都变成小写,

{a=[v1, v2, v3]}

我在 Java 中详细地做了,想知道是否有 simple/better 方式。谢谢

Map<String, Set<String>> result = new HashMap<>();

for (Map.Entry<String, Set<String>> entry : map.entrySet()) {
    String key = entry.getKey().toLowerCase();
    Set<String> currSet = entry.getValue().stream().map(v -> v.toLowerCase()).collect(Collectors.toSet());

    Set<String> existSet = result.get(key);

    if (existSet == null) {
        result.put(key, currSet);
    } else {
        existSet.addAll(currSet);
    }
}

您可以利用 putIfAbsent()computeIfAbsent() 来防止不必要的集合实例化,如果还没有值,则在地图上创建一个新集合,然后调用addAll()

Map<String, Set<String>> result = new HashMap<>();

for (Map.Entry<String, Set<String>> entry : map.entrySet()) {
    String key = entry.getKey().toLowerCase();
    Set<String> currSet = entry.getValue().stream().map(v -> v.toLowerCase()).collect(Collectors.toSet());

    result.computeIfAbsent(key, k -> new HashSet<>()).addAll(currSet);
}

putIfAbsent() 类似,但同样,如果值为 actually 不存在,它将始终实例化一个新的 HashSet 而不是仅实例化一个:

result.putIfAbsent(key, new HashSet<>()).addAll(currSet);

如果您是 java-stream 粉丝:

    @Test
    void mapToMap() {
        // Map.of: Java 9 or higher
        Map<String, Set<String>> before = Map.of("A", Set.of("A", "a"), "a", Set.of("b", "B", "c"));
        
        // Collectors.toMap: Java 8 or higher
        Map<String, Set<String>> after = before.entrySet().stream().collect(
                Collectors.toMap(
                        e -> e.getKey().toLowerCase(),
                        e -> e.getValue().stream().map(String::toLowerCase).collect(Collectors.toSet()),
                        (existing, replacement) -> {
                            existing.addAll(replacement);
                            return existing;
                        }
                )
        );
        assertThat(after.size()).isEqualTo(1);
        assertThat(after.get("a")).containsExactly("a", "b", "c");
    }

你可以这样使用Map.computeIfAbsent()

public static void main(String[] args) throws IOException {
    Map<String, Set<String>> input = Map.of(
        "a", Set.of("v1", "V1"),
        "A", Set.of("v2", "V2", "v3"));

    Map<String, Set<String>> output = new LinkedHashMap<>();
    for (Entry<String, Set<String>> e : input.entrySet())
        output.computeIfAbsent(e.getKey().toLowerCase(), k -> new HashSet<>())
            .addAll(e.getValue().stream().map(String::toLowerCase).toList());

    System.out.println(output);
}

输出:

{a=[v1, v2, v3]}