强制转换为可迭代

时间:2019-03-07 08:44:23

标签: java generics

我有这个静态方法:

  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);

  }

我叫这个:

  private static <T, V, E> void RunMap(
    final Map<String, Iterable<V>> results,
    final Asyncc.IAsyncCallback<Map<String, Iterable<V>>, E> f) { ... }

问题是由于某种原因我无法将Set<V>强制转换为Iterable<V> ...我正在寻找List<V>Set<V>的超类型,我以为Iterable会这样做,但显然不会吗?

我得到的错误是:

  

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>>'

我还试图将List<V>强制转换为Iterable<V>,因为我提到我正在寻找List和Set的超类型。也许只是使用Collection?

更新,我尝试使用:

final Map<String, Collection<V>> results

代替

final Map<String, Iterable<V>> results

我遇到同样的问题。

3 个答案:

答案 0 :(得分:2)

您可以尝试将定义更改为:

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) {

    }

答案 1 :(得分:2)

RunMap声明更改为:

private static <V, E, T extends Iterable<V>> void RunMap(
    final Map<String, T> results,
    final Asyncc.IAsyncCallback<Map<String, T>, E> f) {

Java中的泛型不是协方差的,这意味着当RunMap期望Map<String, Iterable<V>>时,您不能将Map<String, Set<V>>实例传递给它。

要解决此问题,您可以使用有界通配符? extends Vector<V>,但是两个RunMap参数之间存在相关性。两个映射中值的类型必须相同,因此需要定义方法类型T extends Iterable<V>并在定义方法参数的类型时使用它:Map<String, T>和{{1} }。

您可以通过定义Asyncc.IAsyncCallback<Map<String, T>, E>来使声明短一些:

M extends Map<String, ? extends Iterable<V>>

答案 2 :(得分:2)

Map<String, Set<V>>不是Map<String, Iterable<V>>,因为您可以在后者而不是前者上调用此代码:

results.put("", new ArrayList<>());

然后您就失去了类型安全性,因为使用Map<String, Set<V>>的代码期望所有值都是Sets。

您需要在方法签名中为参数添加一个绑定:

final Map<String, ? extends Iterable<V>> results

不能放入results