Record.key
問題は、イテレータが消費されるときに変更される変数の現在の値を返すだけである可能性があると思います(構築時に実際にキー値をキャプチャするレコードを持つのとは対照的です)。例はおそらくそれをより明確にするでしょう。まず、scala REPLを使用して、問題を示さないテストコードを作成しましょう。
case class Record( key: Int )
def getRecordIterator: Iterator[Record] = {
var currentKey: Int = 0
(1 to 10).iterator.map{ i =>
currentKey += 1
new Record( currentKey )
}
}
次に、以下を使用せずに反復を試みることができますgrouped
。
for ((record, i) <- getRecordIterator.zipWithIndex) {
println(i + "|" + record)
}
これにより(予想どおり)
0|Record(1)
1|Record(2)
2|Record(3)
3|Record(4)
4|Record(5)
5|Record(6)
6|Record(7)
7|Record(8)
8|Record(9)
9|Record(10)
そして、使用grouped
:
for (group <- getRecordIterator.zipWithIndex.grouped(3)) {
for ((record, i) <- group) {
println(i + "|" + record)
}
println("---")
}
これは次のようになります。
0|Record(1)
1|Record(2)
2|Record(3)
---
3|Record(4)
4|Record(5)
5|Record(6)
---
6|Record(7)
7|Record(8)
8|Record(9)
---
9|Record(10)
---
今まで、すべてが順調です。
Record
それでは、の定義を少し変更しましょう。
trait Record {
def key: Int
override def toString = "Record(" + key + ")"
}
def getRecordIterator: Iterator[Record] = {
var currentKey: Int = 0
(1 to 10).iterator.map{ i =>
currentKey += 1
new Record{ def key = currentKey }
}
}
この変更により、を使用しない場合でも同じ結果grouped
が得られますが、使用した場合に得られる結果は次のgroup
とおりです。
0|Record(3)
1|Record(3)
2|Record(3)
---
3|Record(6)
4|Record(6)
5|Record(6)
---
6|Record(9)
7|Record(9)
8|Record(9)
---
9|Record(10)
---
next
問題の原因は、イテレータを呼び出すという単なる事実が、によって返される値を変更することですRecord.get
。この問題はさらに簡単に説明できます。
val it = getRecordIterator
val r1 = it.next
println(r1) // prints "Record(1)" as expected
val r2 = it.next
println(r2) // prints "Record(2)" as expected
println(r1) // this now prints "Record(2)", not "Record(1)" anymore!