5

I am seeing some confusing behavior from this code.

def fileArrayMeta = newFile.readLines()
def file3 = fileArrayMeta.collect{ line -> line.split("\\s+") }
println file3[0]
println file3[0].getClass()

The expected result of this operation should be.

=> [, NOTE, *ENTRY, STATEMENT, *.]
=> class java.util.ArrayList

The actual result of this operation is.

=> [, NOTE, *ENTRY, STATEMENT, *.]
=> class [Ljava.lang.String;

Why is this happening?

println file3[0].removeAll("", null)

Exception in thread "main" groovy.lang.MissingMethodException: No signature of method: [Ljava.lang.String;.removeAll() is applicable for argument types: (java.lang.String, null) values: [, null]

I assume this should work too, why not?

def clean4 = clean3.each{it.collect{ it != "" && it != null }}
 println clean4[0]
asked Jan 15, 2015 at 14:13
2
  • L[] is a native array, which has no removeAll. and thou shalt not use each to collect!. Commented Jan 15, 2015 at 15:57
  • if you want to have all non-empty/non-null elements, then just use findAll. e.g. assert ['a',null,''].findAll() == ['a'], as groovy-truth gets rid of them. each just returns the original list and your collect calls are no-ops. Commented Jan 15, 2015 at 21:21

2 Answers 2

10

The split method on java.lang.String returns an array, not an ArrayList. You could use the method tokenize instead (although it doesn't take a regex that's not a problem for the simple case of splitting on whitespace), or convert the array to a list after splitting, using Arrays.asList or as List.

In Groovy split and tokenize both have defaults assuming whitespace as a delimiter, so the regex is not required, either line.split() as List or line.tokenize() is enough. Tabs and spaces both get handled and repetitions work similarly:

groovy:000> s = ' a\tb c d '
===> a b c d
groovy:000> s.tokenize()
===> [a, b, c, d]
groovy:000> s.split() as List
===> [a, b, c, d]

The output [Ljava.lang.String is a notation telling you you have an array of Strings. You can check if something is an array by calling isArray() on the class:

file3[0].class.isArray()

The MissingMethodException is saying you are calling removeAll on an array. You can check the methods available on an object:

groovy:000> a = s.split()
===> [a, b, c, d]
groovy:000> a.class.isArray()
===> true
groovy:000> a.class.methods
===> [public final void java.lang.Object.wait(long,int) throws java.lang.Interru
ptedException, public final native void java.lang.Object.wait(long) throws java.
lang.InterruptedException, public final void java.lang.Object.wait() throws java
.lang.InterruptedException, public boolean java.lang.Object.equals(java.lang.Obj
ect), public java.lang.String java.lang.Object.toString(), public native int jav
a.lang.Object.hashCode(), public final native java.lang.Class java.lang.Object.g
etClass(), public final native void java.lang.Object.notify(), public final nati
ve void java.lang.Object.notifyAll()]
groovy:000> a.class.methods*.toString().grep {it.contains('removeAll')}
===> []

And what do you expect the last example to do? Because the call to collect will return a list of booleans:

groovy> stuff=['asdf', 'zxcv', 'qwerty', '', 'zzz'] 
groovy> stuff.collect { it != '' && it != null } 
Result: [true, true, true, false, true]

The collect method makes a transformed copy of the collection it's called on. But each doesn't return the modified collection, it returns the original unmodified one, here's an example:

groovy> def mylist = ['asdf', 'zxcv', 'qwerty'] 
groovy> def foo = mylist.each {it.toUpperCase()} 
groovy> foo 
Result: [asdf, zxcv, qwerty]

Here the closure in the each has no effect on the contents of mylist or on foo, unlike if you used collect or mylist*.toUpperCase(), which returns the collection of entries created by executing the closure on each element of mylist.

It looks like you are confused about what collect does, and you're trying to use it to filter (which doesn't work). Here's an example of removing empty strings from a list of lists of strings:

groovy> def mylist = [['a', 'b', ''], ['', 'c', 'd'], ['e', '', 'f']] 
groovy> println mylist.collect {it.findAll()} 
[[a, b], [c, d], [e, f]]

The it that findAll is called on is a list of strings.

answered Jan 15, 2015 at 14:16
Sign up to request clarification or add additional context in comments.

7 Comments

@kschmit90: getClass returns something starting with [L, that means it's an array. your output in the question is telling you it's an array of type String.
[Ljava.lang.String mean array of String. [ symbol indicate this
@kschmit90: can you add an example to the question?
@kschmit90: it looks like you're trying to call an ArrayList method removeAll on an array, which doesn't have that method.
@kschmit90: the example at the bottom of the question is incomplete (doesn't specify the contents of clean3) and doesn't specify what the error is. it also seems unrelated to the original question.
|
2

you can also use line.split( /\s+/ ) as List

answered Jan 15, 2015 at 14:17

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.