はじめに
以下のようなリストを逆順で末尾からイテレートしたいケースがあります。
List<String> list = Arrays.asList("A", "B", "C", "D");
でもこれ、意外とスマートにできません。
もちろん以下のようにすることで逆順にすることはできます。
Collections.reverse(list); list.forEach(System.out::println);
しかしこの場合は、元のリスト自体の並びが変わってしまいます。
別のリストを作成して並び替えれば良いですが、リストの要素数が大きい場合は効率が良くありません。
List<String> copy = new ArrayList<>(list);
Collections.reverse(copy);
copy.forEach(System.out::println);
ListIterator による逆順イテレート
Iterator
はイテレートで前進することしかできませんが、ListIterator
は後退することができます。
list.listIterator(list.size())
で末尾に位置する ListIterator
を取得し、previous()
でリストを逆順にイテレートすることができます。
for (ListIterator<String> i = list.listIterator(list.size()); i.hasPrevious();) {
System.out.println(i.previous());
}
ListIterator ユーティリティを利用した逆順イテレート
以下のようなユーティリティを作成します。
public static <T> Iterator<T> descendingIteratorOf(List<T> list) { return new Iterator<T>() { private final ListIterator<T> irt = list.listIterator(list.size()); @Override public boolean hasNext() { return irt.hasPrevious(); } @Override public T next() { return irt.previous(); } }; }
このユーティリティを使えば以下のように
List<String> list = Arrays.asList("A", "B", "C", "D"); descendingIteratorOf(list).forEachRemaining(System.out::println); // D C B A
Stream として扱いたい場合は以下のようにできます。
Iterable<String> iterable = () -> descendingIteratorOf(list); StreamSupport.stream(iterable.spliterator(), false) .map(String::toLowerCase) .forEach(System.out::println); // d c b a
Iterable
を経由させ、StreamSupport
で処理します。
Stream の取得については以下を参照してください。
DescendingIterator による逆順イテレート
元にするリストが LinkedList
や ArrayDeque
のように Deque
インターフェースを実装している場合は、descendingIterator()
を使うことができます。
Deque<String> deque = new LinkedList<>(list); for (Iterator<String> i = deque.descendingIterator(); i.hasNext();) { System.out.println(i.next()); }
以下でも同様です。
deque.descendingIterator().forEachRemaining(System.out::println);
元のリストが ArrayList
などであり、要素数が大きな場合は、LinkedList
インスタンスを新たに作成しなければならないため ListIterator
を利用した方が効率が良いです。
- 作者:Joshua Bloch
- 出版社/メーカー: 丸善出版
- 発売日: 2018/10/30
- メディア: 単行本(ソフトカバー)
- 作者:ケン アーノルド,デビッド ホームズ,ジェームズ ゴスリン
- 出版社/メーカー: 東京電機大学出版局
- 発売日: 2014/05/10
- メディア: 単行本
Head First Java: A Brain-Friendly Guide
- 作者:Kathy Sierra,Bert Bates
- 出版社/メーカー: O'Reilly Media
- 発売日: 2005/02/22
- メディア: ペーパーバック