java Groovy ArrayList 对字符串感到困惑
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27965351/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Groovy ArrayList getting confused for a String
提问by kschmit90
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]
线程“main”中的异常 groovy.lang.MissingMethodException:无方法签名:[Ljava.lang.String;.removeAll() 适用于参数类型:(java.lang.String, null) 值:[, null]
I assume this should work too, why not?
我认为这也应该有效,为什么不呢?
def clean4 = clean3.each{it.collect{ it != "" && it != null }}
println clean4[0]
回答by Nathan Hughes
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
.
java.lang.String 上的 split 方法返回一个数组,而不是一个 ArrayList。您可以改用方法 tokenize(尽管它不需要正则表达式,这对于在空白处进行拆分的简单情况来说不是问题),或者在拆分后使用 Arrays.asList 或 .asList 将数组转换为列表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 中,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]
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:
输出[Ljava.lang.String
是一个符号,告诉您您有一个 Strings 数组。您可以通过在类上调用 isArray() 来检查某个东西是否是数组:
file3[0].class.isArray()
The MissingMethodException is saying you are calling removeAll on an array. You can check the methods available on an object:
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')}
===> []
And what do you expect the last example to do? Because the call to collect will return a list of booleans:
你希望最后一个例子做什么?因为调用 collect 将返回一个布尔值列表:
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:
collect 方法制作它被调用的集合的转换副本。但是每个都不会返回修改后的集合,它返回原始未修改的集合,这是一个例子:
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.
这里 each 中的闭包对 mylist 或 foo 的内容没有影响,与使用 collect 或 foo 不同mylist*.toUpperCase()
,它返回通过对 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:
看起来您对 collect 的作用感到困惑,并且您正在尝试使用它来过滤(这不起作用)。下面是从字符串列表中删除空字符串的示例:
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.
该it
说的findAll被称为上是一个字符串列表。
回答by injecteer
you can also use line.split( /\s+/ ) as List
你也可以使用 line.split( /\s+/ ) as List