GroupingHelper { public <KeyT> Map<KeyT, Set<ValueT>> groupWithDuplicateValues( Function<ValueT, KeyT> keyExtractor) { Map<KeyT, Set<ValueT>> groupedEntities = new HashMap<>(); for (ValueT value : collection) { final KeyT key = keyExtractor.apply(value); Set<ValueT> valuesForKey = groupedEntities.computeIfAbsent(key, k -> new HashSet<>()); valuesForKey.add(value); } return groupedEntities; } GroupingHelper(Collection<ValueT> collection); Map<KeyT, Set<ValueT>> groupWithDuplicateValues(
            Function<ValueT, KeyT> keyExtractor); Map<KeyT, Set<ValueT>> groupWithDuplicateKeysAndValues(Function<ValueT,
            Collection<KeyT>> keysExtractor); Map<KeyT, ValueT> groupUnique(Function<ValueT, KeyT> keyExtractor);  }
@Test public void groupWithDuplicateValues() { Map<Integer, Set<Integer>> expected = new HashMap<>(); expected.put(0, new HashSet<>(Collections.singletonList(1))); expected.put(1, new HashSet<>(Arrays.asList(1, 2))); expected.put(2, new HashSet<>(Arrays.asList(2, 3))); expected.put(3, new HashSet<>(Collections.singletonList(3))); final Map<Integer, Set<Integer>> result = GROUPING_HELPER.groupWithDuplicateKeysAndValues( number -> Arrays.asList(number, number -1)); Assert.assertEquals("Unexpected map content", expected, result); }