Home > front end >  Convert a List to a Map of unique values from the List with key as a single element
Convert a List to a Map of unique values from the List with key as a single element

Time:06-10

I have a list as below -

List<List<String>> originalList = 
    List.of(List.of("C1", "C2", "C3"), List.of("C2", "C3", "C1"));

I am collecting unique elements across lists and arrived at -

Set<String> uniqueValues = originalList.stream()
    .flatMap(Collection::stream)
    .collect(Collectors.toSet());

Now I'm trying to create a map which will look like below -

{C3=[C1, C2], C1=[C3, C2], C2=[C3, C1]}

I have the below snippet -

Map<String, Set<String>> mymap = uniqueValues
            .stream()
            .collect(Collectors.toMap(Function.identity(),
                    value -> uniqueValues, (left, right) -> {
                        left.removeAll(right);
                        return left;
                    }));

which is giving me -

{C3=[C3, C1, C2], C1=[C3, C1, C2], C2=[C3, C1, C2]}

What am I doing wrong ?

CodePudding user response:

Basically, your goal is to create a map where each entry represents a combination generated based on a set uniqueValues.

And obviously each combination is distinct, which means it requires its own Set. I.e. instead of providing the uniqueValues as a value for every key, you need to generate a new HashSet based on the uniqueValues and remove the current key from it.

Another mistake is that you don't need a flavor of toMap() collector that expects three arguments because mergeFunction (the third argument) is meant to resolve duplicates, but there would be no duplicates in the stream since its source is a Set.

To achieve this we need a version of toMap that expects only a keyMapper (a function which produces a key from a stream element) and valueMapper (a function responsible for generating a value from a stream element).

That's how it can be done:

Map<String, Set<String>> myMap = uniqueValues
    .stream()
    .collect(Collectors.toMap(
        Function.identity(),
        str -> {
            Set<String> value = new HashSet<>(uniqueValues);
            value.remove(str);
            return value;
        }
    ));

System.out.println(myMap);

Output:

{C3=[C1, C2], C1=[C3, C2], C2=[C3, C1]}
  • Related