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

如何使用Java 8 Streams API比较HashMap中元素的所有无重复组合并返回符合条件的元素列表

How to Generate Unique Non-Repeating Pairs from a HashMap with Java 8 Streams

Hey there! Let's tackle this problem of creating unique, non-duplicate element pairs from a HashMap using Java 8 Streams. I totally get why your initial double-forEach approach led to duplicates—you were comparing every pair twice (like (A,B) and (B,A)), which isn't what you want. And while reduce is great for aggregating values into a single result, it's not the right tool here. Instead, we can use IntStream to replicate the index-based pairing logic from your pseudo-code, without the repetition.

Step 1: Convert the Entry Set to a List

First, we need to convert the HashMap's entry set into a List because HashMap entries don't support indexed access. This lets us grab elements by position just like your pseudo-code does:

List<Map.Entry<K, V>> entryList = new ArrayList<>(myHashMap.entrySet());

Step 2: Generate Index Pairs Without Duplicates

We'll use IntStream.range to create our outer loop indices (from 0 to the list size minus 2). For each index i, we generate an inner stream of indices j starting at i+1—this ensures we never compare an element with itself, and never repeat a pair in reverse order:

IntStream.range(0, entryList.size())
    .flatMap(i -> IntStream.range(i + 1, entryList.size())
        // ... processing logic here
    )

Step 3: Filter Valid Pairs and Collect Results

For each (i,j) index pair, we fetch the corresponding entries, run your myComparison check, and collect the valid pairs into a list. Here's the full code example:

import java.util.*;
import java.util.function.BiPredicate;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class UniquePairFinder {
    public static <K, V> List<Map.Entry<K, V>[]> findValidPairs(
            HashMap<K, V> myHashMap,
            BiPredicate<Map.Entry<K, V>, Map.Entry<K, V>> myComparison
    ) {
        List<Map.Entry<K, V>> entryList = new ArrayList<>(myHashMap.entrySet());
        
        return IntStream.range(0, entryList.size())
                .flatMap(i -> IntStream.range(i + 1, entryList.size())
                        .mapToObj(j -> new Map.Entry[]{entryList.get(i), entryList.get(j)})
                        .filter(pair -> myComparison.test(pair[0], pair[1]))
                )
                .collect(Collectors.toList());
    }

    // Example usage
    public static void main(String[] args) {
        HashMap<String, Integer> map = new HashMap<>();
        map.put("A", 1);
        map.put("B", 2);
        map.put("C", 3);
        
        // Example comparison: check if first entry's value is less than second's
        BiPredicate<Map.Entry<String, Integer>, Map.Entry<String, Integer>> comparison = 
            (e1, e2) -> e1.getValue() < e2.getValue();
        
        List<Map.Entry<String, Integer>[]> validPairs = findValidPairs(map, comparison);
        
        // Print results
        validPairs.forEach(pair -> 
            System.out.println(pair[0] + " and " + pair[1])
        );
    }
}

Key Notes:

  • No Duplicate Comparisons: By starting j at i+1, we ensure each pair is only checked once—no (B,A) when we already checked (A,B).
  • Why Not Reduce?: reduce is meant for aggregating stream elements into a single result (like summing numbers). Since we need to generate multiple pairs, flatMap with index streams is a much better fit.
  • Customization: If you're using a custom myClass instead of Map.Entry, just replace Map.Entry<K,V> with your class type, and ensure entryList is a list of your custom objects.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.01 02:18:10