关于检查 foo
是集合还是数组的条件:
Class#isAssignableFrom
可能会派上用场。
Class<?> fooClass = foo.getClass();
boolean isArrayOrCollection = Collection.class.isAssignableFrom(fooClass) ||
Object[].class.isAssignableFrom(fooClass);
我合理地假设你不会在基元数组上测试它,因为你有只与包装类一起工作的集合。
我想你可以安全地替换为Object[].class.isAssignableFrom(fooClass)
fooClass.isArray()
boolean isArrayOrCollection = Collection.class.isAssignableFrom(fooClass) ||
fooClass.isArray();
它也适用于原始数组类。
我运行了一个小的“测试”
class Test {
public static void main(String[] args) {
Predicate<Class<?>> p = c -> Collection.class.isAssignableFrom(c) ||
c.isArray();
System.out.println(p.test(new int[0].getClass()));
System.out.println(p.test(new Integer[0].getClass()));
System.out.println(p.test(Collections.emptyList().getClass()));
System.out.println(p.test(Collections.emptySet().getClass()));
System.out.println(p.test(Collections.emptyMap().getClass()));
}
}
这导致
true
true
true
true
false
关于将同时运行数组和集合的泛型循环:
你根本无法编写一个准确的构造来处理这个问题:(或)并且几乎没有共同点(作为一个共同的父级,它的方法是不够的)。Collection
Iterable
Object[]
Object
我认为构建自己的抽象是明智的,它将以相同的方式处理集合和数组。由于没有特定的上下文,我可以提出两个子类的简单想法,每个子类都定义了应该如何迭代其源(集合或数组)。然后,编程到接口将有助于平等地管理它们。
一个非常简化的例子是:
interface Abstraction<T> {
void iterate(Consumer<? super T> action);
static <T> Abstraction<T> of(Collection<T> collection) {
return new CollectionAbstraction<>(collection);
}
static <T> Abstraction<T> of(T[] array) {
return new ArrayAbstraction<>(array);
}
static IntArrayAbstraction of(int[] array) {
return new IntArrayAbstraction(array);
}
}
class CollectionAbstraction<T> implements Abstraction<T> {
Collection<T> source;
public CollectionAbstraction(Collection<T> source) {
this.source = source;
}
@Override
public void iterate(Consumer<? super T> action) {
source.forEach(action);
}
}
class ArrayAbstraction<T> implements Abstraction<T> {
T[] source;
public ArrayAbstraction(T[] source) {
this.source = source;
}
@Override
public void iterate(Consumer<? super T> action) {
for (T t : source) {
action.accept(t);
}
}
}
class IntArrayAbstraction implements Abstraction<Integer> {
int[] source;
public IntArrayAbstraction(int[] source) {
this.source = source;
}
@Override
public void iterate(Consumer<? super Integer> action) {
for (int t : source) {
action.accept(t);
}
}
}
class Test {
public static void main(String[] args) {
Abstraction.of(new Integer[] {1, 2, 3}).iterate(System.out::println);
Abstraction.of(Arrays.asList(1, 2, 3)).iterate(System.out::println);
Abstraction.of(new int[] {1, 2, 3}).iterate(System.out::println);
}
}
我相信上面的方法非常通用。您不依赖于如何迭代某个源,您可以有选择地修改它们。