Skip to content

Instantly share code, notes, and snippets.

@amirci
Last active October 9, 2016 05:58
Show Gist options
  • Save amirci/562d469567986710e2ade675c6030f84 to your computer and use it in GitHub Desktop.
Save amirci/562d469567986710e2ade675c6030f84 to your computer and use it in GitHub Desktop.
 public static <A, B> Optional<Map<B, Set<A>>> tryReverse(final Map<A, Set<B>> maybeInput) {
    return Optional.ofNullable(maybeInput).map(ConfigUtil::reverse);
 }
private static <A, B> Map<B, Set<A>> reverse(final Map<A, Set<B>> input) {
    return filterNullValues(input)
             .flatMap(kvp -> filterNullValues(kvp).map(v -> mkEntry(v, kvp.getKey())))
             .collect(groupingBy(x -> x.getKey(), HashMap::new, mapping(y -> y.getValue(), toSet())));
}
private static <A, B> Map<B, Set<A>> reverse2(final Map<A, Set<B>> input) {
    return filterNullValues(input)
             .reduce(new HashMap<>(),
                     (hsh, kvp) -> { filterNullValues(kvp).forEach(v -> addMulti(hsh, v, kvp.getKey()));
                                     return hsh; },
                     (a, b) -> null); // the last function is used only when running in parallel to concatenate results
}
private static <K, V> Map.Entry<K, V> mkEntry(K key, V value) {
return new AbstractMap.SimpleEntry(key, value);
}
private static <T> Stream<T> filterNullValues(Map.Entry<?, Set<T>> kvp) {
    return kvp.getValue().stream().filter(Objects::nonNull);
}
private static <K, V> Stream<Map.Entry<K, V>> filterNullValues(final Map<K, V> hash) {
    return hash.entrySet().stream().filter(kvp -> Objects.nonNull(kvp.getValue()));
}
private static <A, B> Map<A, Set<B>> addMulti(Map<A, Set<B>> multiMap, A key, B value) {
    multiMap.merge(key,
                   Stream.of(value).collect(toSet()),
                   (s1, s2) -> {s1.addAll(s2); return s1;});
    return multiMap;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment