枚举类型的循环遍历

5

如何循环遍历枚举类型是最好的方式。

我有一个名为Directions的枚举类型,我想要循环遍历它。目前,我已经在枚举中实现了next方法来返回下一个值,但我想知道是否有更好的方式或内置的支持来进行循环遍历。

目前的代码:

enum Direction {
    east, north, west, south;

    Direction next() {

        switch (this) {
        case east:
            return north;

        case north:
            return west;

        case west:
            return south;

        case south:
            return east;
        }

        return null;
    }
}
3个回答

8

实现一个循环的Iterator非常简单:

enum Direction implements Iterable<Direction> {
    east, north, west, south;

    @Override
    public Iterator<Direction> iterator() {
        return new DirectionIterator();
    }

    class DirectionIterator implements Iterator<Direction> {

        Direction next = Direction.this;

        @Override
        public Direction next() {
            try {
                return next;
            } finally {
                next = values()[(next.ordinal() + 1) % values().length];
            }
        }

        @Override
        public boolean hasNext() { 
            return true; 
        }

        @Override
        public void remove() {
            throw new NotImplementedException();
        }
    }
}

使用方法:
public static void main(String[] args) {

    Iterator<Direction> it = Direction.north.iterator();

    for (int i = 0; i < 10; i++)
        System.out.println(it.next());
}

输出:

north
west
south
east
north
west
south
east
north
west

有了aioobe的想法,在枚举本身上放置一个next()方法,甚至可以为所有对iterator()的调用返回相同的迭代器实例。 - Philipp Reichart
哎呀,你说得对。我还没有喝足够的咖啡--关于这个信息应该由调用方持有,而不是迭代器。因此需要为每个调用方提供独立的迭代器。 - Philipp Reichart

7

将枚举类型转换为整数(通过ordinal()),循环后再将其转换回枚举类型(通过values[i])。

像这样:

Direction next() {
    return values()[(ordinal() + 1) % values().length];
}

通用解决方案

循环枚举值的更通用方法是:

class CyclicIterator<T> implements Iterator<T> {

    private final T[] values;
    private int current;

    public CyclicIterator(T[] values) {
        this.values = values;
        this.current = 0;
    }

    @Override
    public boolean hasNext() {
        return true;
    }

    @Override
    public T next() {
        current = (current + 1) % values.length;
        return values[current];
    }
}

以下是如何使用它:

CyclicIterator<Direction> iter = new CyclicIterator<>(Direction.values());
for (int i = 0; i < 6; i++) {
    System.out.println(i + ": " + iter.next());
}

输出:

0: north
1: west
2: south
3: east
4: north
5: west

谷歌Guava解决方案

如果你依赖于谷歌Guava,一个循环迭代器(与上述相同)已经通过Iterators.cycle可用。


1

您可以利用枚举值被分配整数值的事实来循环遍历它们。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接