Java中如何无重复来回遍历列表?解决方向切换重复元素问题
解决ListIterator切换遍历方向时重复读取元素的问题
Java的ListIterator在切换遍历方向时会重复读取当前元素,比如遍历到末尾后调用previous(),会返回最后一个元素本身而非前一个元素。如果不想在业务代码里手动记录遍历方向并调用两次next()/previous(),可以通过以下方案解决:
方案一:基于Guava的ForwardingListIterator封装
利用Guava的ForwardingListIterator简化自定义迭代器编写,仅重写next()和previous()方法处理方向切换逻辑:
import com.google.common.collect.ForwardingListIterator; import java.util.ListIterator; import java.util.NoSuchElementException; enum Direction { NEXT, PREVIOUS, NONE } public class NonRepeatingBidirectionalIterator<E> extends ForwardingListIterator<E> { private final ListIterator<E> delegate; private Direction lastDirection = Direction.NONE; public NonRepeatingBidirectionalIterator(ListIterator<E> delegate) { this.delegate = delegate; } @Override protected ListIterator<E> delegate() { return delegate; } @Override public E next() { // 从previous切换到next时,跳过当前重复元素 if (lastDirection == Direction.PREVIOUS) { super.next(); } lastDirection = Direction.NEXT; return super.next(); } @Override public E previous() { // 从next切换到previous时,跳过当前重复元素 if (lastDirection == Direction.NEXT) { super.previous(); } lastDirection = Direction.PREVIOUS; return super.previous(); } }
使用示例
import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List<String> strings = Arrays.asList("1", "2", "3"); NonRepeatingBidirectionalIterator<String> iterator = new NonRepeatingBidirectionalIterator<>(strings.listIterator()); String first = iterator.next(); // 返回"1" String second = iterator.next(); // 返回"2" String third = iterator.next(); // 返回"3" String fourth = iterator.previous(); // 返回"2",不再重复"3" String fifth = iterator.previous(); // 返回"1" String sixth = iterator.next(); // 返回"2",不再重复"1" } }
方案二:纯Java自定义索引式双向迭代器
如果不想依赖第三方库,可自行实现基于索引的双向迭代器,通过直接控制索引位置避免重复读取:
import java.util.List; import java.util.NoSuchElementException; public class IndexBasedBidirectionalIterator<E> { private final List<E> list; private int currentIndex = -1; private Direction lastDirection = Direction.NONE; public IndexBasedBidirectionalIterator(List<E> list) { this.list = list; } public boolean hasNext() { return currentIndex < list.size() - 1; } public E next() { if (!hasNext()) { throw new NoSuchElementException(); } // 从previous切换到next时,调整索引跳过重复元素 if (lastDirection == Direction.PREVIOUS) { currentIndex++; } lastDirection = Direction.NEXT; return list.get(++currentIndex); } public boolean hasPrevious() { return currentIndex > 0; } public E previous() { if (!hasPrevious()) { throw new NoSuchElementException(); } // 从next切换到previous时,调整索引跳过重复元素 if (lastDirection == Direction.NEXT) { currentIndex--; } lastDirection = Direction.PREVIOUS; return list.get(--currentIndex); } private enum Direction { NEXT, PREVIOUS, NONE } }
使用示例
import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List<String> strings = Arrays.asList("1", "2", "3"); IndexBasedBidirectionalIterator<String> iterator = new IndexBasedBidirectionalIterator<>(strings); String first = iterator.next(); // 返回"1" String second = iterator.next(); // 返回"2" String third = iterator.next(); // 返回"3" String fourth = iterator.previous(); // 返回"2" String fifth = iterator.previous(); // 返回"1" String sixth = iterator.next(); // 返回"2" } }
两种方案均将方向切换逻辑封装在迭代器内部,业务代码无需关心遍历状态,避免了手动记录方向的冗余操作。
内容的提问来源于stack exchange,提问作者Cagepi
相关产品推荐
相关产品推荐

