In Groovy, Is there any way to safely index into a Collection similar to the safe navigation operator?
Asked Answered
C

3

31

This will safely return null without throwing any exceptions

obj?.prop1?.prop2

How can I do that for collections, where it won't throw an index out of bounds exception?

myarray[400]  //how do I make it return null if myarray.size() < 400 

Is there such an operator for Collections?

Cologarithm answered 22/12, 2010 at 18:53 Comment(0)
M
48

That's the default behavior with all collections except arrays in groovy.

assert [1,2,3,4][5] == null
def test = new ArrayList()
assert test[100] == null
assert [1:"one", 2:"two"][3] == null

If you've got an array, cast it to a list.

def realArray = new Object[4]
realArray[100] // throws exception
(realArray as List)[100] // null

You can string list and map indexes together with the ? operator in the same way as with properties:

def myList = [[name: 'foo'], [name: 'bar']]
assert myList[0]?.name == 'foo'
assert myList[1]?.name == 'bar'
assert myList[2]?.name == null
Morry answered 22/12, 2010 at 20:12 Comment(4)
But watch out for negative indices which will cause an exception, ie: def a = [] ; println a[ -1 ] throws a java.lang.ArrayIndexOutOfBoundsExceptionRutherford
@Rutherford any idea why? seems rather inconsistent.Barcarole
an addendum for any groovy noobs like my looking for this, if you need to do map access for variable key names you can use this syntax to take advantage of null-safe operator: mymap = null keyName = "WTF" mymap?."$keyName"Spokesman
Please note, that: test[100] returns null, BUT test.get(100) throws IndexOutOfBoundsException. The same for test?.get(100)Contaminant
B
0

groovy version 3 supports safe index based access for lists, arrays and maps. see https://blog.mrhaki.com/2020/03/groovy-goodness-safe-index-based-access.html

// Using ?[...] will not throw NullPointerException.
assert test?[100] == null
Bulrush answered 18/4, 2024 at 9:33 Comment(0)
H
-1

You can use get() instead:

myarray?.get(400)
Hypochondria answered 20/2, 2018 at 14:10 Comment(4)
This throws an IndexOutOfBoundsException if the index is indeed out of bounds, which is actually worse than the current behavior for myarray[400] which returns null.Electrophone
Actually, you're right. However myarray?.getAt(400) will return null if out of bounds.Hypochondria
For what version of Groovy? I've tested with 2.4.13, 2.4.6, 2.0.0, and 1.7.8.Electrophone
This is not correct. The ? could only help if myarray is null. If myarray is null then calculation of the expression terminates. Otherwise it continuous and tries to access to 400th item which is not exists. And we will get an exception.Solvency

© 2022 - 2025 — McMap. All rights reserved.