Java中的泛型方法应该具有什么签名,以便它可以接受任何<t that =“”implements =“”iteralbe =“”和=“”stores =“”list <u =“”>&gt;和...?

时间:2018-01-29 06:34:51

标签: java generics generic-programming generic-collections

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

&#34;错误&#34;期望的声明:

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,但我找不到实现目标的方式。

3 个答案:

答案 0 :(得分:3)

我的建议:

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的类型相同。

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

答案 1 :(得分:1)

这将符合您的请求,但不严格强制使用返回集合类型来匹配输入类型:

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

我不认为通用接口有一种方法可以在编译时强制执行返回的列表与进入的Collection具有相同的实现。

另请注意,您无法重复使用收集集合或致电new T<...>()。您必须使用反射或其他方法参数。

答案 2 :(得分:1)

伊兰的答案很好。但是,如果您不想通过供应商,则可能需要使用此

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

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