5 回答
TA贡献1906条经验 获得超3个赞
关于检查 foo 是集合还是数组的条件:
类#是可分配的可能派上用场。
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
关于将同时在数组和集合上运行的泛型循环:
你根本无法写一个准确的构造来处理这个问题:(或)并且几乎没有共同点(因为一个共同的父级及其方法是不够的)。CollectionIterableObject[]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);
}
}
我相信上面的方法非常通用。您不依赖于某个源的迭代方式,您可以有选择地修改它们。
TA贡献1803条经验 获得超6个赞
其他答案都在努力回答原始标题问题:
数组和集合是否有通用接口或超类?
但你真正的问题是在身体里:
是否有其他可能性可以像上面这样在一个循环中处理两者?
答案是:不,没有办法编写一个循环访问集合和数组的 for 循环。
你可以跳过一堆箍,把数组变成列表,但你几乎肯定会得到一个比你只写两个(或更多)循环更大的混乱。打电话会告诉你你有什么,但如果没有某种演员,你仍然无法使用它。 不适用于基元数组。getClass().isArray()Arrays.asList()
TA贡献2003条经验 获得超2个赞
根据您要执行的操作,您可能需要实现两种类似的方法:
public <T> void iterateOver(List<T> list) {
// do whatever you want to do with your list
}
public <T> void iterateOver(T[] array) {
this.iterateOver(Arrays.asList(array));
}
或者甚至可能有一个接口:
interface ExtendedIterableConsumer<T> {
public void iterateOver(List<T> list);
public default void iterateOver(T[] array) {
this.iterateOver(Arrays.asList(array));
}
我不确定这是否对你有帮助,因为你似乎已经在某个变量中拥有了有问题的对象。但是,如果你能把这个问题提高一个层次,它可能会很有用。
TA贡献1825条经验 获得超6个赞
您可以使用来自isArray()Class
if (foo != null && (foo.getClass().isArray() || foo instanceof Collection<?>)){
}
编辑:
在迭代此对象方面,没有简单的解决方案。但是,您可以尝试如下操作:foo
private void iterate(@NotNull Object foo) {
if (foo instanceof Collection<?>) {
for (Object o : ((Collection<?>) foo)) {
chandleYourObject(o);
}
}
if (foo.getClass().isArray()) {
if (foo.getClass().isPrimitive()) {
checkPrimitiveTypes(foo);
}
if (foo instanceof Object[]) {
for (Object o : (Object[]) foo) {
chandleYourObject(o);
}
}
}
}
private void checkPrimitiveTypes(Object foo) {
if (foo instanceof int[]) {
for (int i : (int[]) foo) {
}
}
//And the rest of primitive types
}
private void chandleYourObject(Object o ){
//What you want to do with your object
}
TA贡献1859条经验 获得超6个赞
数组是对象:
https://docs.oracle.com/javase/specs/jls/se8/html/jls-10.html
抽象集合还扩展了对象:
https://docs.oracle.com/javase/8/docs/api/java/util/AbstractCollection.html
所以,是的,有一个普通的超类,但不幸的是,这并不能真正帮助你。
我建议你最好的选择是使用:
List<> someList = Arrays.asList(sourceArray)
这会将您的数组转换为实现 Iterable 的集合。您当然需要提前确定初始对象是数组还是集合,并且只有在数组时才调用上述内容,以下是一些执行此操作的选项:
boolean isArray = myArray.getClass().isArray(); boolean isCollection = Collection.class.isAssignableFrom(myList.getClass());
添加回答
举报
