4

基于一个问题,用户想要访问 100000 行文件的第 99999 行,而不必eachLine在前 99998 行上使用闭包进行迭代。所以,我建议他使用

file.readLines().reverse()[1]访问文件的第 99999 行。

这在逻辑上对程序员很有吸引力。但是,我对这种方法实施的复杂性非常怀疑。

reverse()方法仅仅是对程序员隐藏的行的完整迭代的抽象,还是真的像能够迭代尽可能少的行以达到所需的行一样智能?

4

3 回答 3

2

从代码中可以看出,在 Java 中reverse()调用来反转列表。Collections.reverse

但是,非变异代码为您提供了另一种选择。使用listIterator()你可以获得一个迭代器,hasPreviousprevious返回列表,所以如果你这样做:

// 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...

于 2012-07-25T08:05:55.530 回答
0

根据“Javadoc”,它只是以相反的顺序创建一个新列表:

除非我遗漏了什么,否则你是对的,立即跳转光标并不是那么聪明。我的理解是,如果它被索引为一个数组,它可以直接访问它,但如果不是必须遍历一遍。


替代方案可能是:

file.readLines().last()[-1]
于 2012-07-25T07:51:37.413 回答
0

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.

于 2012-07-29T08:15:41.527 回答