'Mapping nested objects using streams to pair all possible combinations in a List

Let's say I've a nested object that contains a distinct pair of String-Integer objects (let's call each such pair as endpoint). There's a List called pair which contains exactly 2 endpoint objects. And another List called pairs that can contain any number of (say n) pair entries and I need to collect every unique pair of Strings along with their corresponding Integer values in a new object.

Consider the following classes for existing object:

    public class Endpoint {
        private String key;
        private Integer number;

        public Endpoint(String key, Integer number) {
            this.key = key;
            this.number = number;
        }

        // Getters, Setters and toString()
    }

    public class Pair {
        // It will have exactly 2 entries
        List<Endpoint> pair;

        public Pair(List<Endpoint> pair) {
            this.pair = pair;
        }

        // Getters, Setters and toString()
    }

Consider the following object (before transformation), where pairs is a List<Pair>. The entries in pairs can be in any order:

pairs: [
        pair: [{"p1",1000},{"p2",2000}],
        pair: [{"p1",3000},{"p3",4000}],
        pair: [{"p2",5000},{"p3",6000}],
        pair: [{"p1",2000},{"p2",3000}],
        pair: [{"p1",2001},{"p2",3001}],
        pair: [{"p1",4000},{"p3",5000}],
        pair: [{"p1",4001},{"p3",5001}],
        pair: [{"p2",6000},{"p3",7000}],
        pair: [{"p2",6001},{"p3",7001}]

]

Consider the following classes to populate the result:

    public class CustomEndpoint {
        private String key;
        // `numbers` can have any number of entries
        private List<Integer> numbers;

        public CustomEndpoint(String key, List<Integer> numbers) {
            this.key = key;
            this.numbers = numbers;
        }

        // Getters, Setters and toString()
    }

    public class CustomPair {
        // It will have exactly 2 entries
        List<CustomEndpoint> pair;

        public CustomPair(List<CustomEndpoint> pair) {
            this.pair = pair;
        }

        // Getters, Setters and toString()
    }

I need to collect it as follows:

custom-pairs: [
    custom-pair: {[{"p1", [1000,2000,2001]}, {"p2", [2000,3000,3001]}]},
    custom-pair: {[{"p1", [3000,4000,4001]}, {"p3", [4000,5000,5001]}]},
    custom-pair: {[{"p2", [5000,6000,6001]}, {"p3", [6000,7000,7001]}]}
]

where custom-pairs is a List<CustomPair>. The order of entries in the numbers List must be maintained as it were for the input pair. e.g Since 1000 in p1 was paired with 2000 in p2, if 1000 is the first entry in numbers List for p1 then 2000 must also be the first entry in numbers List for p2, for the combination where p1 and p2 are paired together.

How can I do this using Streams in Java?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source