Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Java type errors can be nasty
> javac -Xlint:unchecked Transpose.java
Transpose.java:8: error: incompatible types: inference variable R has incompatible bounds
return map.entrySet().stream().collect(toMap(e -> e.getValue(), e -> new HashSet<>(Set.of(e.getKey())), (x, y) -> {x.addAll(y); return x;}));
^
equality constraints: Map<K,U>
upper bounds: HashMap<B,HashSet<A#2>>,Object
where R,A#1,T#1,K,T#2,U,B,A#2 are type-variables:
R extends Object declared in method <R,A#1>collect(Collector<? super T#1,A#1,R>)
A#1 extends Object declared in method <R,A#1>collect(Collector<? super T#1,A#1,R>)
T#1 extends Object declared in interface Stream
K extends Object declared in method <T#2,K,U>toMap(Function<? super T#2,? extends K>,Function<? super T#2,? extends U>,BinaryOperator<U>)
T#2 extends Object declared in method <T#2,K,U>toMap(Function<? super T#2,? extends K>,Function<? super T#2,? extends U>,BinaryOperator<U>)
U extends Object declared in method <T#2,K,U>toMap(Function<? super T#2,? extends K>,Function<? super T#2,? extends U>,BinaryOperator<U>)
B extends Object declared in method <A#2,B>transposeMap(HashMap<A#2,B>)
A#2 extends Object declared in method <A#2,B>transposeMap(HashMap<A#2,B>)
1 error
# This is probably an instance of this bug: https://bugs.openjdk.java.net/browse/JDK-8196762 the proper solution (adding a type witness) is described there and here: https://stackoverflow.com/questions/38089827/collector-doesnt-match-wildcard-in-result-type
# though the wildcard in `toMap` makes it quite puzzling to understand what to fill in. Casting the result of the computation is unfortunately much easier :/
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import static java.util.stream.Collectors.toMap;
class Transpose{
static <A, B> HashMap<B, HashSet<A>> transposeMap(HashMap<A, B> map){
return map.entrySet().stream().collect(toMap(e -> e.getValue(), e -> new HashSet<>(Set.of(e.getKey())), (x, y) -> {x.addAll(y); return x;}));
}
}
@gcapizzi

This comment has been minimized.

Copy link

commented Sep 3, 2018

Questo compila:

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import static java.util.stream.Collectors.toMap;

public class Transpose {
    static <A, B> Map<B, HashSet<A>> transposeMap(HashMap<A, B> map) {
        return map
                .entrySet()
                .stream()
                .collect(toMap(
                        Map.Entry::getValue,
                        e -> new HashSet<>(Set.of(e.getKey())),
                        (x, y) -> {
                            x.addAll(y);
                            return x;
                        }
                ));
    }

    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("one", 1);
        map.put("two", 2);
        map.put("three", 3);
        map.put("other-three", 3);

        System.out.println(transposeMap(map));
    }
}

Output:

{1=[one], 2=[two], 3=[other-three, three]}

Il problema è che toMap è un Collector<T, ?, Map<K,U>> e non un Collector<T, ?, HashMap<K,U>>. Stavi assumendo uno specifico tipo di mappa, cosa che toMap non garantisce in nessun modo. Detto questo, il messaggio di errore è terribile.

Inoltre io mi limiterei a dipendere dalle interfacce Map e Set anziché da specifiche implementazioni. La signature di trasposeMap dovrebbe essere:

static <A, B> Map<B, Set<A>> transposeMap(Map<A, B> map)
@berdario

This comment has been minimized.

Copy link
Owner Author

commented Sep 3, 2018

👍

As you noticed, a concrete Set implementation is still needed since as you noticed addAll is an optional operation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.