Apparently, you are considering a disordered pair, where the pair (a, b) matches the pair (b, a). You must create a class yourself for this purpose, for example.
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, pa) && Objects.equals(this.b, pb) || Objects.equals(this.a, pb) && Objects.equals(this.b, pa); } @Override public int hashCode() { return Objects.hashCode(a) + Objects.hashCode(b); } }
Having a class with the required semantics, you can just create all the combinations and let the Stream API remove duplicates. This will even work if the original list already has duplicates:
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());
You did not indicate whether the element should be paired with itself. If not, you can filter out these cases:
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());
As a side note, if building your result type is a side effect free and not expensive, and the type has an equality that reflects the two input elements, you can consider their construction instead of Pair instances and use .distinct for them, while preserving the conversion of Pair instances to instances YourNewObjectType .
If there are no duplicates in your original list, you can use this knowledge to create unique pairs based on indexes:
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());
If pairing the element with itself is unacceptable, just translate the comment /*+ 1*/ into a real +1 . This code is less readable, but potentially more efficient.