0

Let's say I have a tuple (1, 2). I want to create a stream, that gives me all possible combinations of that tuples' values. So I want to create a stream that looks like this:

[(1, 1), (1, 2), (2, 1), (2, 2)]

This is my class for my tuples:

public class Tuple<T> {
    private final T first;
    private final T second;

    public Tuple(T first, T second) {
        assert first != null;
        assert second != null;

        this.first = first;
        this.second = second;
    }

    public T getFirst() {
        return first;
    }

    public T getSecond() {
        return second;
    }

    @Override
    ...

This is my class for my tuple-set:

public class TupleSet<T> implements Set<Tuple<T>> {
    private Set<T> set;
    public TupleSet(Set<T> set) {
        this.set = set;
        //This is where I want to create my tuple-set
    }
   
    public Stream<Tuple<T>> getElements() {
    return; //This is where I want to return a stream of that tuple-set
}

How can I get my desired tuple-set using permutation?

I am aware, that there are multiple example for creating permutations, but I am struggeling with the Tuple<T>-type I have to return it in.

Tuples always have 2 elements. Although they can be created out of sets with different lenghts. If I insert the set [0, 1, 2, 3] I want to get that tuple list: [(0,0),(1,1),(2,2),(3,3),(0,1),(0,2)(0,3),(1,0),(1,2),(1,3),(2,0),(2,1),(2,3),(3,0)(3,1),(3,2)] so 16 tuple values in total.

Stefan Zobel
  • 3,182
  • 7
  • 28
  • 38

2 Answers2

1

You can pre-generate a set of all possible combinations of tuples Set<Tuple<T>> when creating a TupleSet<T> object, and then return a stream over that set as follows:

Try it online!

public static class Tuple<T> {
    private final T first, second;

    public Tuple(T first, T second) {
        assert first != null;
        assert second != null;

        this.first = first;
        this.second = second;
    }

    public T getFirst() { return first; }
    public T getSecond() { return second; }

    @Override
    public String toString() { return "(" + first + ", " + second + ")"; }
}
public static class TupleSet<T> {
    private Set<T> set;
    private Set<Tuple<T>> elements;

    public TupleSet(Set<T> set) {
        this.set = set;
        this.elements = set.stream()
                .flatMap(i -> set.stream().map(j -> new Tuple<>(i, j)))
                .collect(Collectors.toCollection(LinkedHashSet::new));
    }

    public Stream<Tuple<T>> getElements() {
        return elements.stream();
    }
}
public static void main(String[] args) {
    TupleSet<Integer> tupleSet =
            new TupleSet<>(new LinkedHashSet<>(List.of(1, 2, 3)));
    // output
    tupleSet.getElements().forEach(System.out::println);
}

Output:

(1, 1)
(1, 2)
(1, 3)
(2, 1)
(2, 2)
(2, 3)
(3, 1)
(3, 2)
(3, 3)

See also: How to use streams to find pairs of elements from two lists or array multiplication

0

A brute-force solution would be to iterate Set<T> set in a nested way and apply flatMap to create <Stream<Tuple<T>>:

public Stream<Tuple<T>> getElements() {
    return set.stream()
            .flatMap(first -> set.stream()
                    .map(second -> new Tuple(first, second)));
}
Nowhere Man
  • 19,170
  • 9
  • 17
  • 42