根据一个问题,用户希望访问100000行文件的第99999行,而不必在前99998行使用eachLine
闭包进行迭代。所以,我建议他使用
file.readLines().reverse()[1]
访问文件的第99999行。
这在逻辑上对程序员很有吸引力。然而,我对实施这一方法的复杂性表示怀疑。
reverse()
方法仅仅是对程序员隐藏的行上的完整迭代的抽象吗?还是它真的很智能,能够迭代尽可能少的行来达到所需的行?
从代码中可以看到,reverse()
在Java中调用Collections.reverse
来反转列表。
然而,非变异代码为您提供了另一种选择。使用listIterator()
,您可以获得一个带有hasPrevious
和previous
的迭代器来遍历列表,因此如果您这样做:
// Our list
def a = [ 1, 2, 3, 4 ]
// Get a list iterator pointing at the end
def listIterator = a.listIterator( a.size() )
// Wrap the previous calls in another iterator
def iter = [ hasNext:{ listIterator.hasPrevious() },
next:{ listIterator.previous() } ] as Iterator
然后我们可以做:
// Check the value of 1 element from the end of the list
assert iter[ 1 ] == 3
然而,所有这些都是一个隐藏的ArrayList,所以如果你只这样做,几乎可以肯定会更快(更容易读取代码):
assert a[ 2 ] == 3
而不是所有的逆转。虽然很明显,这需要分析以确保我是对的。。。
根据"Javadoc",它只是以相反的顺序创建一个新列表:
- http://groovy.codehaus.org/groovy-jdk/java/util/List.html
除非我遗漏了什么,否则你是对的——立即跳转光标并不明智。我的理解是,如果它被索引为一个数组,它可以直接访问它,但如果不是,就必须进行迭代。
备选方案可能是:
file.readLines().last()[-1]
这个答案:
def a= [1, 2, 3, 4]
def listIterator= a.listIterator(a.size())
def iter= [hasNext: {listIterator.hasPrevious()},
next: {listIterator.previous()}] as Iterator
assert iter[1] == 3
仅适用于Groovy-1.7.2及以后版本。
在Groovy-1.7.1、1.7.0、1.7 beta、1.6、1.5和1.0-RC-01中,它找不到代理的getAt(1)方法调用。对于1.0-RC-06及之前的版本,java.util.HashMap不能强制转换为java.util.Iterator.