Java Groovy ArrayList对字符串感到困惑

Java Groovy ArrayList对字符串感到困惑,java,arrays,string,file,groovy,Java,Arrays,String,File,Groovy,我从这段代码中看到一些令人困惑的行为 def fileArrayMeta = newFile.readLines() def file3 = fileArrayMeta.collect{ line -> line.split("\\s+") } println file3[0] println file3[0].getClass() 此操作的预期结果应为 => [, NOTE, *ENTRY, STATEMENT, *.] => class java.util.ArrayL

我从这段代码中看到一些令人困惑的行为

def fileArrayMeta  = newFile.readLines()
def file3 = fileArrayMeta.collect{ line -> line.split("\\s+") }
println file3[0]
println file3[0].getClass()
此操作的预期结果应为

=> [, NOTE, *ENTRY, STATEMENT, *.]
=> class java.util.ArrayList
此操作的实际结果是

=> [, NOTE, *ENTRY, STATEMENT, *.]
=> class [Ljava.lang.String;
为什么会这样

println file3[0].removeAll("", null)
线程“main”groovy.lang.MissingMethodException中的异常:没有方法[Ljava.lang.String;的签名。removeAll()适用于参数类型: (java.lang.String,null)值:[,null]

我想这也应该有效,为什么不呢

def clean4 = clean3.each{it.collect{ it != "" && it != null }}
    println clean4[0]

java.lang.String上的split方法返回一个数组,而不是ArrayList。您可以改用tokenize方法(尽管它不需要正则表达式,对于在空格上拆分的简单情况来说这不是问题),或者在拆分后使用Arrays.asList或
as list
将数组转换为列表

在Groovy中,split和tokenize都有默认值,假定空格作为分隔符,因此不需要正则表达式,无论是
line.split()as List
还是
line.tokenize()
都足够了。制表符和空格都会得到处理,重复的工作方式类似:

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]

输出
[Ljava.lang.String
为。您可以通过调用类上的isArray()来检查某个对象是否为数组:

file3[0].class.isArray()
MissingMethodException表示您正在数组上调用removeAll。您可以检查对象上可用的方法:

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')}
===> []
您希望最后一个示例做什么?因为对collect的调用将返回一个布尔值列表:

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

Result: [true, true, true, false, true]
collect方法生成其调用的集合的转换副本。但每个方法都不返回修改后的集合,而是返回原始的未修改集合,以下是一个示例:

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

Result: [asdf, zxcv, qwerty]
这里,each中的闭包对mylist或foo的内容没有影响,这与使用collect或
mylist*.toUpperCase()
不同,后者返回通过对mylist的每个元素执行闭包创建的条目集合

看起来您对collect的功能感到困惑,并且试图使用它进行筛选(这不起作用)。下面是一个从字符串列表中删除空字符串的示例:

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

[[a, b], [c, d], [e, f]]

调用findAll的
it
是一个字符串列表。

您也可以使用
line.split(/\s+/)as list

@kschmit90:getClass返回以[L开头的内容,这意味着它是一个数组。问题中的输出告诉您它是一个字符串类型的数组。
[Ljava.lang.String
表示字符串数组。
[
符号表示this@kschmit90:您能为问题添加一个示例吗?@kschmit90:看起来您试图调用数组中没有该方法的ArrayList方法removeAll。@kschmit90:问题底部的示例不完整(不指定clean3的内容)也不指定错误是什么。它似乎与原始问题无关。
L[]
是一个本机数组,它没有
removeAll
。您不能使用每个元素来收集。如果您想拥有所有非空/非空元素,只需使用
findAll
。例如
断言['a',null',].findAll()=['a']
,因为groovy truth已经摆脱了它们。
每个
都只返回原始列表,而您的
collect
调用是无效的。