39

The question is as simple as the title. How to check in Groovy that object is a list or collection or array? But can't find a simple way of checking it. Any ideas?

Andrey Adamovich
  • 20,285
  • 14
  • 94
  • 132

6 Answers6

45

A List is a Collection, so the checks aren't mutually exclusive:

def foo = ...
boolean isCollection = foo instanceof Collection
boolean isList = foo instanceof List
boolean isSet = foo instanceof Set
boolean isArray = foo != null && foo.getClass().isArray()
Burt Beckwith
  • 75,342
  • 5
  • 143
  • 156
  • 1
    That's the same way I can do it in Java :). So, no Groovy way? – Andrey Adamovich Sep 01 '11 at 19:27
  • "boolean isArray = foo instanceof Object[]" should work too. If foo is null it will return false and not throw an Exception. – John Wagenleitner Sep 01 '11 at 23:12
  • 4
    +1 for not reinventing the wheel. IMHO the Java syntax is pretty concise in this case, and a lot more readable than the suggested groovy-way solution. – peterp Aug 23 '13 at 08:06
  • I agree with peterp... but I find it curious that Groovy doesn't supply a simple way to run such a test (unless it now 2018-02-14 does, of course ...) – mike rodent Feb 14 '18 at 19:26
  • FWIW this works perfectly with Hashes too: Swap the two map defs around and see: ``` def map = [me: 'you', him: 'her'] // def map = 'just a string' if (map instanceof HashMap) { println 'hash' } else { println 'not hash' } ``` – Max Cascone Jun 03 '20 at 20:32
42

I don't know if you need to distinguish between Collection, List and Array, or just want to know if an object is any of these types. If the latter, you could use this:

boolean isCollectionOrArray(object) {    
    [Collection, Object[]].any { it.isAssignableFrom(object.getClass()) }
}

// some tests
assert isCollectionOrArray([])
assert isCollectionOrArray([] as Set)
assert isCollectionOrArray([].toArray())
assert !isCollectionOrArray("str")

Run the code above in the Groovy console to confirm it behaves as advertised

Dónal
  • 185,044
  • 174
  • 569
  • 824
7

If you are looking for a Groovy way, look at in operator. It is actually a combination of Class.isAssignableFrom(Class<?>) and Class.isInstance(Object) meaning that you can use it to test classes as well as objects.

// Test classes
assert ArrayList in Collection
assert ArrayList in List
assert HashSet in Collection
assert HashSet in Set

// Test objects
def list = [] as ArrayList
def set = [] as HashSet

assert list in Collection
assert list in List
assert set in Collection
assert set in Set

Testing if an object is an array may be tricky. I would recommend @BurtBeckwith's approach.

def array = [].toArray()

assert array.getClass().isArray()
pgiecek
  • 7,970
  • 4
  • 39
  • 47
3

I use this to "arrayfy" an object, if its already a collection then it will return a copy, else wrap it in a list. So you don't need to check it while processing, it will be always a collection.

def arrayfy = {[] + it ?: [it]}
def list = arrayfy(object) // will be always a list
plajko
  • 381
  • 2
  • 9
1

Usually you'd want to check its behavior with duck typing.

def foo = someMethod()
if (foo.metaClass.respondsTo('each')) {
  foo.each {println it}
}
Dónal
  • 185,044
  • 174
  • 569
  • 824
Adam Stegman
  • 1,013
  • 10
  • 14
  • 1
    String respondsTo each as well, I think – Andrey Adamovich Sep 01 '11 at 19:30
  • 1
    Groovy adds the `each` method to `Object` so every object responds to `each`. Therefore, this proposal is faulty. – Dónal Sep 02 '11 at 10:00
  • 1
    Yikes, I didn't realize `Object` responded to `each`. Either way, you'd want to check the method you're actually going to use, so if you're using a different method this might work ok. If you do plan to use `each` then unfortunately this won't be sufficient. – Adam Stegman Sep 03 '11 at 16:50
  • why not just use the object's class to determine it's type instead of checking for the presence of a particular method? I don't see any benefit to using this approach over `instanceof`? – Dónal Sep 04 '11 at 11:25
  • 2
    The benefit of duck typing is that you're not hard-coding a particular implementation. A caller can use your documentation to decide what to pass if they prefer a different implementation (or their own, for instance). – Adam Stegman Sep 05 '11 at 02:45
0

Just use the instanceof operator and check if the object is an instance of java.util.Collection

Simone
  • 2,261
  • 2
  • 19
  • 27
  • Burt answered that, there's no groovy way..but i'd also try object instanceof Object[]...but absolutely not sure about it – Simone Sep 01 '11 at 19:30