如何检查对象是否是 Java 中的集合类型?

通过使用 Java 反射,我们可以很容易地知道一个对象是否是一个数组。判断一个对象是否是一个集合(Set,List,Map,Vector...)最简单的方法是什么?

125312 次浏览
if (x instanceof Collection<?>){
}


if (x instanceof Map<?,?>){
}

Have you thinked about using instanceof ? Like, say

if(myObject instanceof Collection) {
Collection myCollection = (Collection) myObject;

Although not that pure OOP style, it is however largely used for so-called "type escalation".

Test if the object implements either java.util.Collection or java.util.Map. (Map has to be tested separately because it isn't a sub-interface of Collection.)

Update: there are two possible scenarios here:

  1. You are determining if an object is a collection;

  2. You are determining if a class is a collection.

The solutions are slightly different but the principles are the same. You also need to define what exactly constitutes a "collection". Implementing either Collection or Map will cover the Java Collections.

Solution 1:

public static boolean isCollection(Object ob) {
return ob instanceof Collection || ob instanceof Map;
}

Solution 2:

public static boolean isClassCollection(Class c) {
return Collection.class.isAssignableFrom(c) || Map.class.isAssignableFrom(c);
}

(1) can also be implemented in terms of (2):

public static boolean isCollection(Object ob) {
return ob != null && isClassCollection(ob.getClass());
}

I don't think the efficiency of either method will be greatly different from the other.

Java conveniently has the instanceof operator (JLS 15.20.2) to test if a given object is of a given type.

 if (x instanceof List<?>) {
List<?> list = (List<?>) x;
// do something with list
} else if (x instanceof Collection<?>) {
Collection<?> col = (Collection<?>) x;
// do something with col
}

One thing should be mentioned here: it's important in these kinds of constructs to check in the right order. You will find that if you had swapped the order of the check in the above snippet, the code will still compile, but it will no longer work. That is the following code doesn't work:

 // DOESN'T WORK! Wrong order!
if (x instanceof Collection<?>) {
Collection<?> col = (Collection<?>) x;
// do something with col
} else if (x instanceof List<?>) { // this will never be reached!
List<?> list = (List<?>) x;
// do something with list
}

The problem is that a List<?> is-a Collection<?>, so it will pass the first test, and the else means that it will never reach the second test. You have to test from the most specific to the most general type.

Since you mentioned reflection in your question;

boolean isArray = myArray.getClass().isArray();
boolean isCollection = Collection.class.isAssignableFrom(myList.getClass());
boolean isMap = Map.class.isAssignableFrom(myMap.getClass());