Jagger
Jagger

Reputation: 10524

Collect to a TreeMap in one line using Collator

I have the following piece of code.

import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

public final class Main {
    public static void main(final String[] args) {
        final Object[][] pairs = { { "Arka Gdynia", Collections.emptyList() },
                { "Legia Warszawa", Collections.emptyList() }, { "ŁKS Łódź", Collections.emptyList() },
                { "Śląsk Wrocław", Collections.emptyList() }, { "Wisła Kraków", Collections.emptyList() }, };

        final Map<String, Object> clubPlayerMap = Arrays.stream(pairs)
                .collect(Collectors.toMap(c -> c[0].toString(), c -> c[1], (o1, o2) -> o1, TreeMap::new));
        for (final String key : clubPlayerMap.keySet()) {
            System.out.println(key);
        }
    }
}

This unfortunately does not produce the result I want. The keys need to be sorted according to Polish collation.

Arka Gdynia
Legia Warszawa
Wisła Kraków
ŁKS Łódź
Śląsk Wrocław

The result I expect is

Arka Gdynia
Legia Warszawa
ŁKS Łódź
Śląsk Wrocław
Wisła Kraków

So I googled and found a way to do this with java.text.Collator. I am wondering however whether it is possible to do it as one-liner together with stream() and collect().

The solution I came up with is the following, but unfortunately it is not very neat.

import java.text.Collator;
import java.util.Arrays;
import java.util.Collections;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

public final class Main {
    public static void main(final String[] args) {
        final Object[][] pairs = { { "Arka Gdynia", Collections.emptyList() },
                { "Legia Warszawa", Collections.emptyList() }, { "ŁKS Łódź", Collections.emptyList() },
                { "Śląsk Wrocław", Collections.emptyList() }, { "Wisła Kraków", Collections.emptyList() }, };

        final Map<String, Object> clubPlayerMapCollated = new TreeMap<>(Collator.getInstance(new Locale("pl", "PL")));
        final Map<String, Object> clubPlayerMap = Arrays.stream(pairs)
                .collect(Collectors.toMap(c -> c[0].toString(), c -> c[1], (o1, o2) -> o1, TreeMap::new));
        clubPlayerMapCollated.putAll(clubPlayerMap);
        for (final String key : clubPlayerMapCollated.keySet()) {
            System.out.println(key);
        }
    }
}

Is it at all possible to produce the map from a one-liner?

Upvotes: 1

Views: 325

Answers (1)

Eran
Eran

Reputation: 393936

Instead of passing a method reference to the default constructor (TreeMap::new), pass a lambda expression that would generate the desired TreeMap:

final Map<String, Object> clubPlayerMap = 
    Arrays.stream(pairs)
          .collect(Collectors.toMap(c -> c[0].toString(), 
                                    c -> c[1], 
                                    (o1, o2) -> o1, 
                                    () -> new TreeMap<>(Collator.getInstance(new Locale("pl", "PL")))));

Upvotes: 2

Related Questions