As usual, but the original code to be refactored was just too evil and had to be fixed.
package chapter11; import org.junit.jupiter.api.Test; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.toSet; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; public class DataGroupingOperationsTest { interface Scores { Map<Integer, Set<String>> namesForScores(final Map<String, Integer> scores); } public static class ScoresBefore implements Scores { public Map<Integer, Set<String>> namesForScores(final Map<String, Integer> scores) { final Map<Integer, Set<String>> result = new HashMap<>(); for (Map.Entry<String, Integer> entry : scores.entrySet()) { final String name = entry.getKey(); final Integer score = entry.getValue(); if (!result.containsKey(score)) { result.put(score, new HashSet<>()); } result.get(score).add(name); } return result; } } public static class ScoresAfter implements Scores { public Map<Integer, Set<String>> namesForScores(final Map<String, Integer> scores) { return scores.keySet().stream() .collect(groupingBy(scores::get, toSet())); } } private static void commonNamesForScoresTests(final Scores scores) { assertAll( () -> assertEquals(Map.of(), scores.namesForScores(Map.of())), () -> assertEquals( Map.of(1, Set.of("Jill")), scores.namesForScores(Map.of("Jill", 1))), () -> assertEquals( Map.of(1, Set.of("Jill"), 2, Set.of("Paul")), scores.namesForScores(Map.of("Jill", 1, "Paul", 2))), () -> assertEquals( Map.of(1, Set.of("Jill", "Kate"), 2, Set.of("Paul")), scores.namesForScores(Map.of("Jill", 1, "Paul", 2, "Kate", 1))) ); } @Test void scoresBefore() { commonNamesForScoresTests(new ScoresBefore()); } @Test void scoresAfter() { commonNamesForScoresTests(new ScoresAfter()); } }