torutkのブログ

ソフトウェア・エンジニアのブログ

java.util.ListIteratorのnextとpreviousの振る舞いメモ

JavaFXでページめくりをするUIを作るにあたって、その処理の中で、ページ名を格納したListからlistIteratorを取得し、ページめくり操作のUIとして用意した[前へ]、[次へ]ボタンを押すと、listIteratorのprevious、nextで次のページ名を取得する実装をしてみました。

すると、[次へ]でいくつかめくった後に[前へ]を押すと、1回目はページが前に戻らず2回目にページが前に戻るという現象が生じました。

  • ここで、既にListIteratorの振る舞いを分かっている人は、「あっ、やっちまったね」とすぐに分かるのかと思います。

さっそく、挙動を確かめるべく、JDK 9のREPL環境であるjshellで振る舞いを確かめてみます。

C:\Users\torutk>jshell
|  JShellへようこそ -- バージョン9-ea
|  概要については、次を入力してください: /help intro

jshell> List<String> data = Arrays.asList("Alfa", "Bravo", "Charlie", "Delta");
data ==> [Alfa, Bravo, Charlie, Delta]

jshell> ListIterator<String> lit = data.listIterator();
lit ==> java.util.AbstractList$ListItr@2ef5e5e3

jshell> lit.next()
$3 ==> "Alfa"

jshell> lit.next()
$4 ==> "Bravo"

jshell> lit.next()
$5 ==> "Charlie"

jshell> lit.previous()
$6 ==> "Charlie"

jshell> lit.previous()
$7 ==> "Bravo"

jshell> lit.next()
$8 ==> "Bravo"

と、まず4つのページ名を入れたListを作成し、ListIteratorを取得します。
next()やprevious()を適宜呼んでみたところ、next方向にイテレートしているときはprevious()で取得するものは、直前のnext()で取得したものと同じものになります。
previous方向にイテレートしているときは、next()で取得するものは、直前のprevious()で取得したものと同じになります。

JavaDoc APIJava SE 8のjava.util.ListIterator)を見ると
https://docs.oracle.com/javase/jp/8/docs/api/java/util/ListIterator.html

ListIteratorには現在の要素がありません。そのカーソル位置は常に、previous()呼出しによって返される要素と、next()呼出しによって返される要素との間にあります。

と説明が記載されていました。

ページめくりのように、現在表示しているページとその1つ前、1つ後を扱うには、ListIteratorではなく、独自にモデルを作成するのがよさそうです。