代码之家  ›  专栏  ›  技术社区  ›  Dmitrii Demenev

Java中的泛型方法应该具有什么签名,以便它可以接受任何实现Iteralbe并存储List和。。。?

  •  3
  • Dmitrii Demenev  · 技术社区  · 6 年前

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

    “错误”所需声明:

    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 回复  |  直到 6 年前
        1
  •  3
  •   Eran    6 年前

    我的建议:

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

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

    例如,您可以传递 ArrayList<ArrayList<String>> 输入并获取 HashSet<LinkedList<String>> 如果通过 HashSet::new 供应商代替 ArrayList::new 在上述示例中。

        2
  •  1
  •   tkruse    6 年前

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

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

    我认为泛型接口无法在编译时强制执行返回的列表与进入的集合具有相同的实现。

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

        3
  •  1
  •   lucidbrot    6 年前

    埃兰的回答很好。但是,如果您不想超过供应商,您可能需要使用此选项

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

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