Reputation: 100000
I have this static method:
static <V, T, E> void GroupToSets(
final Iterable<T> items,
final Asyncc.IAsyncCallback<Map<String, Set<V>>, E> f) {
final HashMap<String, Set<V>> results = new HashMap<>();
final Iterator<T> iterator = items.iterator();
if (!iterator.hasNext()) {
f.done(null, results);
return;
}
RunMap((Map<String, Iterable<V>>)results, f);
}
And I am calling this:
private static <T, V, E> void RunMap(
final Map<String, Iterable<V>> results,
final Asyncc.IAsyncCallback<Map<String, Iterable<V>>, E> f) { ... }
the problem is for some reason I can't cast a Set<V>
to Iterable<V>
...I am looking for a supertype for both List<V>
and Set<V>
, I thought Iterable would do that but apparently not?
The error I am getting is:
Inconvertible types; cannot cast
'java.util.HashMap<java.lang.String,java.util.Set<V>>' to
'java.util.Map<java.lang.String,java.lang.Iterable<V>>'
I am also trying to cast List<V>
to Iterable<V>
as I mentioned I am looking for a supertype for both List and Set..maybe just use Collection?
Update, I tried using:
final Map<String, Collection<V>> results
instead of
final Map<String, Iterable<V>> results
I get the same problem.
Upvotes: 2
Views: 659
Reputation: 16039
Change the RunMap
declaration to:
private static <V, E, T extends Iterable<V>> void RunMap(
final Map<String, T> results,
final Asyncc.IAsyncCallback<Map<String, T>, E> f) {
Generics in Java are not covariance, it means when RunMap
expects a Map<String, Iterable<V>>
you cannot pass to it a Map<String, Set<V>>
instance.
To solve this you can use a bounded wildcard ? extends Vector<V>
, however there is a correlation between the two RunMap
arguments. The type of the values in the the two maps must be the same, therefore you need to define a method type T extends Iterable<V>
and use it when defining the type of the method arguments: Map<String, T>
and Asyncc.IAsyncCallback<Map<String, T>, E>
.
You can make the declaration a bit shorter by defining M extends Map<String, ? extends Iterable<V>>
:
private static <V, E, M extends Map<String, ? extends Iterable<V>>> void RunMap(
final M results,
final Asyncc.IAsyncCallback<M, E> f) {
Upvotes: 2
Reputation: 9
You could try changing the definition to:
static <V, T, E> void GroupToSets(
final Iterable<T> items,
final Asyncc.IAsyncCallback<Map<String, ? extends Iterable<V>>, E> f) {
final Map<String, ? extends Set<V>> results = new HashMap<>();
final Iterator<T> iterator = items.iterator();
if (!iterator.hasNext()) {
f.done(null, results);
return;
}
RunMap(results, f);
}
static <T, V, E> void RunMap(
final Map<String, ? extends Iterable<V>> results,
final Asyncc.IAsyncCallback<Map<String, ? extends Iterable<V>>, E> f) {
}
Upvotes: 0
Reputation: 140318
A Map<String, Set<V>>
is not a Map<String, Iterable<V>>
, because you can invoke this code on the latter, but not the former:
results.put("", new ArrayList<>());
and then you have broken type safety, because code using a Map<String, Set<V>>
expects all values to be Sets.
You need to add a bound to the parameter in the method signature:
final Map<String, ? extends Iterable<V>> results
which precludes putting into results
.
Upvotes: 2