显然,您考虑一个无序对,其中pair(a,b)与pair(b,a)相同。为此,您必须自己创建一个类,例如
class Pair<T> { final T a, b; public Pair(T a, T b) { this.a = a; this.b = b; } @Override public boolean equals(Object obj) { if(obj==this) return true; if(!(obj instanceof Pair)) return false; Pair<?> p=(Pair<?>)obj; return Objects.equals(this.a, p.a) && Objects.equals(this.b, p.b) || Objects.equals(this.a, p.b) && Objects.equals(this.b, p.a); } @Override public int hashCode() { return Objects.hashCode(a) + Objects.hashCode(b); }}有了一个具有所需语义的类,您可以简单地创建所有组合并让Stream API删除重复项。如果源列表已经重复,这甚至可以工作:
List<YourNewObjectType> result = objectList.stream() .flatMap(objA -> objectList.stream().map(objB -> new Pair<>(objA,objB))) .distinct() .filter(pair -> condition) .map(pair -> new YourNewObjectType … ) .collect(Collectors.toList());
您未指定是否允许某个元素与其自身配对。如果没有,您可以过滤掉以下情况:
List<YourNewObjectType> result = objectList.stream() .flatMap(objA -> objectList.stream() .filter(objB -> !Objects.equals(objA, objB)) .map(objB -> new Pair<>(objA,objB))) .distinct() .filter(pair -> condition) .map(pair -> new YourNewObjectType … ) .collect(Collectors.toList());
附带说明一下,如果结果类型的构造没有副作用且不昂贵,并且该类型具有反映两个输入元素的相等性,则可以考虑构造它们而不是
Pair实例并
.distinct用于它们,从而节省了转换
Pair实例到
YourNewObjectType实例。
如果您的源列表中没有重复项,则可以利用这些知识基于索引构建唯一对:
List<YourNewObjectType> result = IntStream.range(0, objectList.size()) .mapToObj(i -> IntStream.range(i, objectList.size()) .mapToObj(j -> new Pair<>(objectList.get(i),objectList.get(j)))) .flatMap(Function.identity()) .filter(pair -> condition) .map(pair -> new YourNewObjectType … */) .collect(Collectors.toList());
如果不允许将元素与自身配对,只需将
注释变为real即可+1。该代码可读性较差,但可能更有效。



