基于一个问题,用户想要访问 100000 行文件的第 99999 行,而不必eachLine
在前 99998 行上使用闭包进行迭代。所以,我建议他使用
file.readLines().reverse()[1]
访问文件的第 99999 行。
这在逻辑上对程序员很有吸引力。但是,我对这种方法实施的复杂性非常怀疑。
该reverse()
方法仅仅是对程序员隐藏的行的完整迭代的抽象,还是真的像能够迭代尽可能少的行以达到所需的行一样智能?
从代码中可以看出,在 Java 中reverse()
调用来反转列表。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
Rather than all the reversing. Though obviously, this would need profiling to make sure I'm right...
根据“Javadoc”,它只是以相反的顺序创建一个新列表:
除非我遗漏了什么,否则你是对的,立即跳转光标并不是那么聪明。我的理解是,如果它被索引为一个数组,它可以直接访问它,但如果不是必须遍历一遍。
替代方案可能是:
file.readLines().last()[-1]
This answer:
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
only works in Groovy-1.7.2 and after.
In Groovy-1.7.1, 1.7.0, the 1.7 betas, 1.6, 1.5, and back to 1.0-RC-01, it doesn't find the getAt(1) method call for the proxy. For version 1.0-RC-06 and before, java.util.HashMap cannot be cast to java.util.Iterator.