groovy中的reverse()方法仅仅是一个迭代的抽象



根据一个问题,用户希望访问100000行文件的第99999行,而不必在前99998行使用eachLine闭包进行迭代。所以,我建议他使用

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

这在逻辑上对程序员很有吸引力。然而,我对实施这一方法的复杂性表示怀疑。

reverse()方法仅仅是对程序员隐藏的行上的完整迭代的抽象吗?还是它真的很智能,能够迭代尽可能少的行来达到所需的行?

从代码中可以看到,reverse()在Java中调用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

而不是所有的逆转。虽然很明显,这需要分析以确保我是对的。。。

根据"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.

最新更新