17

I've tried:

groovy:000> Set<String> s = ["a", "b", "c", "c"]
===> [a, b, c]
groovy:000> s
Unknown property: s

I want to be able to use this as a set, but even if I pass it explicitly, it turns it into an ArrayList:

groovy:000> joinList(["a", "b", "c", "c"])
ERROR groovy.lang.MissingMethodException:
No signature of method: groovysh_evaluate.joinList() is applicable for argument types: (java.util.ArrayList) values: [[a, b, c, c]]
Possible solutions: joinList(java.util.Set)
reectrix
  • 7,999
  • 20
  • 53
  • 81

2 Answers2

53

This problem only occurs because you're using the Groovy Shell to test your code. I don't use the Groovy shell much, but it seems to ignore types, such that

Set<String> s = ["a", "b", "c", "c"]

is equivalent to

def s = ["a", "b", "c", "c"]

and the latter does of course create a List. If you run the same code in the Groovy console instead, you'll see that it does actually create a Set

Set<String> s = ["a", "b", "c", "c"]
assert s instanceof Set

Other ways to create a Set in Groovy include

["a", "b", "c", "c"].toSet()

or

["a", "b", "c", "c"] as Set
Dónal
  • 185,044
  • 174
  • 569
  • 824
  • Ah, okay. So you're recommending to use the console instead to solve this? – reectrix Jan 08 '15 at 19:56
  • 1
    @smilingcow yes, I don't know why the Groovy shell ignores types like this, but I tend to use the console instead for these kinds of quick tests – Dónal Jan 08 '15 at 19:57
  • groovysh ain't no REPL – cfrick Jan 08 '15 at 21:40
  • 1
    Interesting. ["a", "b", "c", "c"] as Set made my unit tests fail, but ["a", "b", "c", "c"].toSet() is working fine. I'm using Spock. – Patrycja K Oct 17 '16 at 14:09
  • Upvoted because it mentions `toSet()` - very useful. – Per Lundberg Oct 31 '18 at 13:56
  • 1
    @PatrycjaK I just fell about it too in Spock, because there's a difference: ... as Set creates a LinkedHashSet, .toSet() creates a HashSet. That broke my mocking, as in production code a KeySet was used, which is an ancestor of HashSet but not of LinkedHashSet. – julianwki Feb 20 '20 at 11:53
18

Groovy >= 2.4.0
Setting interpreterMode to true in groovy shell by

:set interpreterMode true

should fix this issue

Groovy < 2.4.0
Adding a type to the variable makes it a local variable which is not available to shell's environment.

use as below in groovysh

groovy:000> s = ['a', 'b', 'c', 'c'] as Set<String>
===> [a, b, c]
groovy:000> s
===> [a, b, c]
groovy:000> s.class
===> class java.util.LinkedHashSet
groovy:000>
dmahapatro
  • 49,365
  • 7
  • 88
  • 117
  • you've omitted types in your example, so everything proceeds as expected. Any idea why the Groovy Shell seems to ignores types which leads to the kind of misunderstandings described in this question? – Dónal Jan 09 '15 at 04:17
  • 2
    Adding a type to the variable makes it a local variable which is not available to shell's environment. @Dónal – dmahapatro Jan 09 '15 at 05:16