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
;例如,它可以是 LinkedList
、ArrayList
或任何其他 Collection
; U
- 是另一种需要记忆的类型;我要创建的方法应该 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;
}
当然,您需要一些更好的异常处理,但此示例代码按我的预期工作。
我想创建一个遍历存储 ArrayList<U>
的任何集合的方法 - 让我们调用该集合 T
;例如,它可以是 LinkedList
、ArrayList
或任何其他 Collection
; U
- 是另一种需要记忆的类型;我要创建的方法应该 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;
}
当然,您需要一些更好的异常处理,但此示例代码按我的预期工作。