Groovy ArrayList 对字符串感到困惑
Groovy ArrayList getting confused for a String
我从这段代码中看到了一些令人困惑的行为。
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 return 上的 split 方法是一个数组,而不是 ArrayList。您可以改用方法标记化(尽管它不需要正则表达式,这对于在空格上拆分的简单情况来说不是问题),或者在拆分后使用 Arrays.asList 或 [=16 将数组转换为列表=].
在 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
是a notation telling you you have an array of Strings。您可以通过在 class 上调用 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 的调用将 return 一个布尔值列表:
groovy> stuff=['asdf', 'zxcv', 'qwerty', '', 'zzz']
groovy> stuff.collect { it != '' && it != null }
Result: [true, true, true, false, true]
collect 方法生成调用它的集合的转换副本。但是每个都不是 return 修改后的集合,它 return 是原始的未修改集合,这是一个例子:
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()
不同,后者 return 是通过执行关闭 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
我从这段代码中看到了一些令人困惑的行为。
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 return 上的 split 方法是一个数组,而不是 ArrayList。您可以改用方法标记化(尽管它不需要正则表达式,这对于在空格上拆分的简单情况来说不是问题),或者在拆分后使用 Arrays.asList 或 [=16 将数组转换为列表=].
在 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
是a notation telling you you have an array of Strings。您可以通过在 class 上调用 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 的调用将 return 一个布尔值列表:
groovy> stuff=['asdf', 'zxcv', 'qwerty', '', 'zzz']
groovy> stuff.collect { it != '' && it != null }
Result: [true, true, true, false, true]
collect 方法生成调用它的集合的转换副本。但是每个都不是 return 修改后的集合,它 return 是原始的未修改集合,这是一个例子:
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()
不同,后者 return 是通过执行关闭 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