What's the best way to extract a single value from a Set in groovy?

11,492

Solution 1

A few alternatives, none of them very pretty:

set.iterator()[0]
set.find { true }
set.collect { it }[0]

Finally, if it's guaranteed that that set has only one item:

def e
set.each { e = it }

The underlying issue, of course, is that Java Sets provide no defined order (as mentioned in the Javadoc), and hence no ability to get the nth element (discussed in this question and this one). Hence, any solution is always to somehow convert the set to a list.

My guess is that either of the first two options involve the least data-copying, as they needn't construct a complete list of the set, but for a one-element set, that should hardly be a concern.

Solution 2

One other possibility (which will work in Java or Groovy):

set.iterator().next()

Solution 3

Since Java 8, here is another solution that will work for both Java and Groovy:

set.stream().findFirst().get()

Solution 4

Even when this question is quite old, I am sharing my just a bit prettier solution.

(set as List).first()
(set as List)[0]

If you need to take null into account (not the case in this question):

(set as List)?.first()
(set as List)?.get(index)

Hope it helps! :)

Share:
11,492

Related videos on Youtube

ataylor
Author by

ataylor

Updated on January 25, 2020

Comments

  • ataylor
    ataylor about 4 years

    If I have a Set that I know contains a single element, what's the best way to extract it? The best I can come up with is this, but it doesn't feel very groovy:

    set = [1] as Set
    e = set.toList()[0]
    assert e == 1
    

    If I'm dealing with a list, I've got lots of nice ways to get the element, none of which seem to work with Sets:

    def list = [1]
    e = list[0]
    (e) = list
    e = list.head()
    
    • Binil Thomas
      Binil Thomas about 13 years
      The 'groovy feel' is a very subjective thing. If I were writing the code, I will be happy with set.toList().first(). :-)
  • Oleg Estekhin
    Oleg Estekhin about 9 years
    There is Collection.find() method since 1.8.1, which is a bit shorter to use than set.find{ true }

Related