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 API(Java SE 8のjava.util.ListIterator)を見ると
https://docs.oracle.com/javase/jp/8/docs/api/java/util/ListIterator.html
ListIteratorには現在の要素がありません。そのカーソル位置は常に、previous()呼出しによって返される要素と、next()呼出しによって返される要素との間にあります。
と説明が記載されていました。
ページめくりのように、現在表示しているページとその1つ前、1つ後を扱うには、ListIteratorではなく、独自にモデルを作成するのがよさそうです。