You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 18:42:45