50

Let the code speak first

def bars = foo.listBars()
def firstBar = bars ? bars.first() : null
def firstBarBetter = foo.listBars()?.getAt(0)

Is there a more elegant or idiomatic way to get the first element of a list, or null if it's not possible? (I wouldn't consider a try-catch block elegant here.)

alain.janinm
  • 19,951
  • 10
  • 65
  • 112
Adam Schmideg
  • 10,590
  • 10
  • 53
  • 83
  • What does #listBars return? Groovy shouldn't throw if you try to get an element that doesn't exist from a list. `final l = []` `assert l[0] == null` `assert l.getAt(0) == null` `assert l instanceof ArrayList` – Justin Piper May 01 '12 at 15:19

3 Answers3

76

Not sure using find is most elegant or idiomatic, but it is concise and wont throw an IndexOutOfBoundsException.

def foo 

foo = ['bar', 'baz']
assert "bar" == foo?.find { true }

foo = []
assert null == foo?.find { true }

foo = null
assert null == foo?.find { true }  

--Update Groovy 1.8.1
you can simply use foo?.find() without the closure. It will return the first Groovy Truth element in the list or null if foo is null or the list is empty.

M-Razavi
  • 3,327
  • 2
  • 34
  • 46
John Wagenleitner
  • 10,967
  • 1
  • 40
  • 39
  • 8
    +1 for this trick. I could make it even more concise: `foo?.find{ it }` – Adam Schmideg Feb 09 '11 at 11:50
  • 5
    Adam, [0].find{it} returns null – tixxit Nov 21 '11 at 19:02
  • 2
    This would make a great convenience method addition to Groovy maps as "first()" – Josh Diehl May 04 '12 at 07:47
  • I know this is an older thread, but I was looking for a similar answer. At first I tried a "foo?[0]" syntax. I think that would be pretty cool, so you could do "foo?[1]", "foo?[2]",... as well. – Steve Ardis Mar 14 '17 at 20:33
  • 10
    Since Groovy 1.8.1, you can simply use `foo?.find()` without the closure. It will return the first Groovy Truth element in the list or null if foo is null or the list is empty. [source](http://docs.groovy-lang.org/latest/html/groovy-jdk/java/util/Collection.html#find()) – Tony Baguette Apr 19 '17 at 15:15
  • @AdamSchmideg, want to extend tixxit comment: ```[null, new Object()].find {it}``` will return object, but not null element. – Vitaliy Borisok Apr 03 '18 at 14:02
27

You could also do

foo[0]

This will throw a NullPointerException when foo is null, but it will return a null value on an empty list, unlike foo.first() which will throw an exception on empty.

James McMahon
  • 48,506
  • 64
  • 207
  • 283
  • thanks for sharing! I was getting stuck around idiomatic solution for first element after findAll on a list that could be empty in the first place, or after the findAll and this gave me what I needed – IT Gumby Jan 22 '15 at 22:30
3

Since Groovy 1.8.1 we can use the methods take() and drop(). With the take() method we get items from the beginning of the List. We pass the number of items we want as an argument to the method.

To remove items from the beginning of the List we can use the drop() method. Pass the number of items to drop as an argument to the method.

Note that the original list is not changed, the result of take()/drop() method is a new list.

def a = [1,2,3,4]

println(a.drop(2))
println(a.take(2))
println(a.take(0))
println(a)

*******************
Output:
[3, 4]
[1, 2]
[]
[1, 2, 3, 4]
Here_2_learn
  • 5,013
  • 15
  • 50
  • 68
  • 3
    If you're going to copy-n-paste the text directly from the Excellent MrHaki, at least include a link to his site: https://blog.mrhaki.com/2011/09/groovy-goodness-take-and-drop-items.html – Patrice M. Apr 05 '21 at 03:39