Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cyclic traversal over enum

Tags:

java

enums

what is the best way of cyclic traversal over an enum.

I have an enum Directions and i want to traverse over it cyclically. currently i have implemented next method in enum which returns next value, i was just wondering is there any better way/inbuilt support for cyclic traversal.

current code

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;
    }
}
like image 395
banjara Avatar asked May 28 '12 11:05

banjara


2 Answers

It would be pretty simple to implement an cyclic 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();
        }
    }
}

Usage:

public static void main(String[] args) {

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

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

Outputs:

north
west
south
east
north
west
south
east
north
west
like image 74
dacwe Avatar answered Sep 20 '22 15:09

dacwe


Convert to int (through ordinal()), cycle and convert back to enum (through values[i]).

Like this:

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

Generic Solution

A more generic way of cycling through enum values is:

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];
    }
}

Which can be used as follows:

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

Output:

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

Guava solution

If you depend on Guava, a cyclic iterator (identical to the one above) is already available through Iterators.cycle

like image 37
aioobe Avatar answered Sep 21 '22 15:09

aioobe