You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何高效拆分含Multimap的Java Map中的真假条目

高效拆分Map<String, Multimap<Boolean, String>>为两个目标Map的方案

要高效完成拆分,核心是一次遍历原集合避免重复迭代,同时利用Guava Multimap的视图特性减少不必要的数据拷贝。以下是Java 8及以下版本的两种实现方式,分别适用于不同场景:

一、传统循环实现(最高效,一次遍历)

这种方式仅遍历原Map一次,同时填充两个目标Map,适合对性能要求极高的场景。可根据需求选择直接使用视图(无拷贝)或创建独立集合(拷贝数据):

1. 使用视图(无拷贝,性能最优)

如果不需要修改拆分后的Multimap,且能接受原集合修改会影响目标集合的情况,直接用Guava的Multimaps.filterKeys生成视图:

import com.google.common.collect.*;

public class MultimapSplitter {
    public static void split(Map<String, Multimap<Boolean, String>> originalMap,
                            Map<String, Multimap<Boolean, String>> trueEntriesMap,
                            Map<String, Multimap<Boolean, String>> falseEntriesMap) {
        // 清空目标Map,避免原有数据干扰
        trueEntriesMap.clear();
        falseEntriesMap.clear();

        // 一次遍历原Map,同时处理true和false条目
        for (Map.Entry<String, Multimap<Boolean, String>> entry : originalMap.entrySet()) {
            String outerKey = entry.getKey();
            Multimap<Boolean, String> innerMultimap = entry.getValue();

            // 生成仅包含true条目的视图Multimap
            Multimap<Boolean, String> trueSubmap = Multimaps.filterKeys(innerMultimap, Boolean::booleanValue);
            if (!trueSubmap.isEmpty()) {
                trueEntriesMap.put(outerKey, trueSubmap);
            }

            // 生成仅包含false条目的视图Multimap
            Multimap<Boolean, String> falseSubmap = Multimaps.filterKeys(innerMultimap, f -> !f);
            if (!falseSubmap.isEmpty()) {
                falseEntriesMap.put(outerKey, falseSubmap);
            }
        }
    }

    // 使用示例
    public static void main(String[] args) {
        Map<String, Multimap<Boolean, String>> original = Maps.newHashMap();
        Multimap<Boolean, String> mm1 = ArrayListMultimap.create();
        mm1.put(true, "a");
        mm1.put(true, "b");
        mm1.put(false, "c");
        original.put("key1", mm1);

        Multimap<Boolean, String> mm2 = ArrayListMultimap.create();
        mm2.put(false, "d");
        original.put("key2", mm2);

        Map<String, Multimap<Boolean, String>> trueMap = Maps.newHashMapWithExpectedSize(original.size());
        Map<String, Multimap<Boolean, String>> falseMap = Maps.newHashMapWithExpectedSize(original.size());

        split(original, trueMap, falseMap);
    }
}

2. 创建独立集合(拷贝数据,与原集合解耦)

如果需要拆分后的集合独立于原集合(修改原集合不影响目标集合),则将视图拷贝为新的Multimap实现:

将上述代码中的视图创建部分替换为:

// 拷贝true条目到新的ArrayListMultimap
Multimap<Boolean, String> trueSubmap = ArrayListMultimap.create(Multimaps.filterKeys(innerMultimap, Boolean::booleanValue));

二、Java 8 Stream实现(代码简洁,需两次遍历)

如果对性能要求稍低,追求代码简洁,可以使用Stream API,缺点是会遍历原Map两次:

import com.google.common.collect.*;
import java.util.Map;
import java.util.stream.Collectors;

public class StreamMultimapSplitter {
    public static void main(String[] args) {
        Map<String, Multimap<Boolean, String>> original = Maps.newHashMap();
        // 初始化原集合...

        // 构建仅包含true条目的Map
        Map<String, Multimap<Boolean, String>> trueMap = original.entrySet().stream()
                .filter(entry -> !entry.getValue().get(true).isEmpty())
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        entry -> ArrayListMultimap.create(Multimaps.filterKeys(entry.getValue(), Boolean::booleanValue))
                ));

        // 构建仅包含false条目的Map
        Map<String, Multimap<Boolean, String>> falseMap = original.entrySet().stream()
                .filter(entry -> !entry.getValue().get(false).isEmpty())
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        entry -> ArrayListMultimap.create(Multimaps.filterKeys(entry.getValue(), f -> !f))
                ));
    }
}

性能优化关键点

  • 一次遍历优先:传统循环方式仅遍历原集合一次,避免Stream方式两次遍历的额外开销
  • 利用视图减少拷贝:Guava的filterKeys返回的是视图,无需复制数据,性能最优;仅在需要解耦时才进行拷贝
  • 初始化指定预期大小:使用Maps.newHashMapWithExpectedSize(original.size())初始化目标Map,避免HashMap扩容带来的性能损耗

内容的提问来源于stack exchange,提问作者Timothy Clotworthy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 02:13:19