Java 中的泛型方法应该有什么签名才能接受任何 <T that implements Iteralbe and stores List<U>> 和...?

What signature should a generic method in Java have so that It can accept any <T that implements Iteralbe and stores List<U>> and...?

我想创建一个遍历存储 ArrayList<U> 的任何集合的方法 - 让我们调用该集合 T;例如,它可以是 LinkedListArrayList 或任何其他 CollectionU - 是另一种需要记忆的类型;我要创建的方法应该 return 相同的集合 T 但它应该存储 LinkedList<U> 而不是。

"Wrong" 所需声明:

public <T extends Collection, U> T<LinkedList<U>> rewrap (T<ArrayList<U>> arrayList) {
    T<LinkedList<U>> linkedList = new T<LinkedList<U>>();
    // do some stuff here
    return linkedList;
}

我仔细阅读了 documentation 但我没有找到实现目标的方法。

我的建议:

public static <T, C extends Collection<LinkedList<T>>> C rewrap (Collection<ArrayList<T>> in, Supplier<C> collectionFactory) {

    C out = collectionFactory.get ();

    for (ArrayList<T> list : in) {
      out.add (new LinkedList<T> (list));
    }

    return out;
}

请注意,您必须传递 Supplier 以便该方法能够创建所需类型的 Collection 实例。

用法:

ArrayList<ArrayList<String>> in = new ArrayList<> ();
in.add (new ArrayList<String> ());
in.get (0).add ("abc");
ArrayList<LinkedList<String>> out = rewrap (in, ArrayList::new);

编辑:您应该注意,此方法不要求输出外部 Collection 的类型与输入外部 Collection.

的类型相同

例如,如果您传递 HashSet::new 供应商而不是上例中的 ArrayList::new,则可以传递 ArrayList<ArrayList<String>> 输入并获得 HashSet<LinkedList<String>> 输出。

这将符合您的要求,但不会严格执行 return 集合类型以匹配输入类型:

public <U> List<LinkedList<U>> rewrap(Collection<ArrayList<U>> arrayList) {
    T linkedList = ...
    // do some stuff here
    return linkedList;
}

我认为通用接口没有办法在编译时强制执行 returned 列表与进入的 Collection 具有相同的实现。

另请注意,您不能重复使用传入集合或调用 new T<...>()。您将不得不使用反射或其他方法参数。

Eran 的回答很好。但是,如果您不想通过供应商,则可能需要求助于此

public static void main(String[] args) {
    // create inner list
    ArrayList<String> innerList = new ArrayList<>();
    innerList.add("test string 1"); innerList.add("test string 2");
    // add it to outer List twice because why not
    ArrayList<ArrayList<String>> outerList = new ArrayList<>();
    outerList.add(innerList); outerList.add(innerList);
    // rewrap it
    ArrayList<LinkedList<String>> rewrapped = rewrap(outerList);
    System.out.println("rewrapped.");
}

public static <T, C extends Collection<LinkedList<T>>> C rewrap (Collection<ArrayList<T>> in) {

    Collection<LinkedList<T>> out = null;
    try {
        out = (in.getClass().newInstance());
    } catch (InstantiationException | IllegalAccessException e) {
        e.printStackTrace();
    }
    C myC = (C) out;

    for (ArrayList<T> list : in) {
        myC.add (new LinkedList<T> (list));
    }

    return myC;
}

当然,您需要一些更好的异常处理,但此示例代码按我的预期工作。