Gilbert Williams
Gilbert Williams

Reputation: 1050

Creating an iterator in Java

I have the following class:

public abstract class MapObjects<MapleMapObject> {
    private Map map;
    private HashMap<Integer, MapleMapObject> objects;

    public MapObjects(Map map) {
        this.map = map;
        this.objects = new HashMap<>();
    }

    public void add(MapleMapObject object) {
        objects.put(map.getObjectId(), object);

        onAdd();
    }

    public void remove(MapleMapObject object) {
        onRemove();

        objects.remove(object.getObjectId());
    }

    protected abstract void onAdd();

    protected abstract void onRemove();
}

I want to create an iterator so I can iterate over classes that extend from this class. For example, if I have a class named MapCharacters extends MapObjects<Character>, I want to be able to do the following:

characters = new MapCharacters(this);
for (Character character : characters)

How can this be achieved?

Upvotes: 4

Views: 179

Answers (2)

Paul Boddington
Paul Boddington

Reputation: 37665

You can return objects.values().iterator() but you should be aware that this iterator has a remove() method that you can use to remove entries from objects without onRemove() being called. This may or may not be what you want.

If this is not what you want, you can return an Iterator where the remove method throws an UnsupportedOperationException:

return Collections.unmodifiableCollection(objects.values()).iterator();

Alternatively, if you want an Iterator with a remove method that removes an entry and invokes your onRemove() method, you would have to write a class implementing Iterator yourself. I think something like this would work.

public abstract class MapObjects<MapleMapObject> implements Iterable<MapleMapObject> {

    ...

    @Override 
    public Iterator<MapleMapObject> iterator() {
        return new Iterator<MapleMapObject>() {

            private final Iterator<MapleMapObject> iterator = objects.values().iterator();

            @Override
            public boolean hasNext() {
                return iterator.hasNext();
            }

            @Override
            public MapleMapObject next() {
                return iterator.next();
            }

            @Override
            public void remove() {
                onRemove();
                iterator.remove();
            }
        };
    }
}

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1503779

If you just want to be able to iterate over objects map, you can just call values() on that and then create an iterator from that value set:

public abstract class MapObjects<MapleMapObject> implements Iterable<MapleMapObject> {

    ...

    @Override public Iterator<MapleMapObject> iterator() {
        return objects.values().iterator();
    }
}

Upvotes: 9

Related Questions