DodgyCodeException
DodgyCodeException

Reputation: 6123

Java 8 streams groupingBy using a Comparator

I'm interested in turning the following code into something more succinct:

    final String[] strings = {"a", "B", "A", "á", "Á"};
    final Collator collator = Collator.getInstance(Locale.FRANCE);
    collator.setStrength(Collator.PRIMARY);

    final Map<String, Set<String>> m = new TreeMap<>(collator);
    for (String s : strings) {
        m.compute(s, (k, v) -> {
            if (v == null)
                v = new TreeSet<String>();
            v.add(s);
            return v;
        });
    }

    final Collection<Set<String>> requiredResult = m.values();

    requiredResult.forEach(System.out::println);

Output:

[A, a, Á, á]
[B]

Basically what this does is consider letters as equal by ignoring case and diacritical marks and group such "equal" letters together. (By the way, I'm aware that most languages don't consider letters equal if the differ by diacritical mark; this is just a contrived example.)

I was thinking of shortening it by using streams. However, the groupingBy collector requires things to be grouped by a letter. I don't have a specific letter here, just a Comparator (the collator).

Upvotes: 2

Views: 3108

Answers (1)

Nikolai
Nikolai

Reputation: 785

Maybe such way:

final String[] strings = {"a", "B", "A", "á", "Á"};
final Collator collator = Collator.getInstance(Locale.FRANCE);
collator.setStrength(Collator.PRIMARY);

Collection<Set<String>> result = Arrays.stream(strings)
            .collect(Collectors.groupingBy(collator::getCollationKey, Collectors.toSet()))
            .values();
System.out.println(result); //[[a, A, á, Á], [B]]

Upvotes: 5

Related Questions