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

如何统计Guava ListMultimap中每组值的出现次数?

统计Guava ListMultimap中值组的出现次数

你需要统计Multimap里每个键对应的两个字符串组成的组合的出现频率,之前用自定义Storage类配合Collections.frequency没得到正确结果,大概率是因为Storage类没有正确重写equals()和hashCode()方法——毕竟Java默认的对象相等判断是基于引用的,不是内容。下面给你两种可行的解决方案:

方案一:用Guava的ImmutablePair直接统计

既然你已经在使用Guava,直接用它的ImmutablePair来封装每个键对应的两个字符串,然后用Guava的Multiset(专门用来统计元素出现次数的集合)来统计频率,会非常方便:

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutablePair;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Multiset;
import com.google.common.collect.HashMultiset;
import java.util.List;

public class MultimapStats {
    public static void main(String[] args) {
        // 模拟你的Multimap数据
        ListMultimap<Integer, String> multimap = ArrayListMultimap.create();
        multimap.put(1, "key");
        multimap.put(1, "car");
        multimap.put(2, "key");
        multimap.put(2, "blue");
        multimap.put(3, "key");
        multimap.put(3, "car");

        // 把每个key对应的两个字符串转成ImmutablePair,存入Multiset统计次数
        Multiset<ImmutablePair<String, String>> pairMultiset = HashMultiset.create();
        for (Integer key : multimap.keySet()) {
            // 匹配你的添加逻辑:每个key对应两个值
            List<String> values = multimap.get(key);
            if (values.size() == 2) {
                ImmutablePair<String, String> pair = ImmutablePair.of(values.get(0), values.get(1));
                pairMultiset.add(pair);
            }
        }

        // 输出统计结果
        System.out.println("[key,car]出现次数:" + pairMultiset.count(ImmutablePair.of("key", "car"))); // 输出2
        System.out.println("[key,blue]出现次数:" + pairMultiset.count(ImmutablePair.of("key", "blue"))); // 输出1
    }
}

方案二:修复自定义Storage类的equals和hashCode

如果你坚持用自己的Storage类,必须重写equals()和hashCode(),让Java能识别内容相同的对象。比如:

import java.util.Objects;

class Storage {
    private String str1;
    private String str2;

    public Storage(String str1, String str2) {
        this.str1 = str1;
        this.str2 = str2;
    }

    // 重写equals,判断两个Storage的内容是否完全一致
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Storage storage = (Storage) o;
        return Objects.equals(str1, storage.str1) && Objects.equals(str2, storage.str2);
    }

    // 重写hashCode,基于两个字符串的哈希值生成,保证equals相等的对象hashCode也相等
    @Override
    public int hashCode() {
        return Objects.hash(str1, str2);
    }
}

修复后再用Collections.frequency或者普通HashMap统计就没问题了:

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

public class StorageStats {
    public static void main(String[] args) {
        HashMap<Integer, Storage> map = new HashMap<>();
        map.put(1, new Storage("key", "car"));
        map.put(2, new Storage("key", "blue"));
        map.put(3, new Storage("key", "car"));

        List<Storage> storageList = new ArrayList<>(map.values());
        int carCount = Collections.frequency(storageList, new Storage("key", "car"));
        System.out.println(carCount); // 输出2
    }
}

为什么之前的方法失败?

Collections.frequency依赖对象的equals()方法来判断是否相等,Java默认的equals()是比较对象的内存地址,而不是内容。所以即使两个Storage对象的字符串内容一样,它们也是不同的对象,frequency自然会统计错误。重写equals和hashCode后,就能让Java正确识别内容相同的对象了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:50:13