4

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?

2
  • 1
    For the enhanced for loop syntax to work, MapCharacters must implement Iterable<Character>. Commented Sep 10, 2015 at 19:26
  • Why do you use MapObjects<MapleMapObject> in your code sample and then talk about MapObjects<Character> in your question? You should make it generic? Commented Sep 10, 2015 at 19:30

2 Answers 2

9

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();
    }
}
Sign up to request clarification or add additional context in comments.

Comments

0

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();
            }
        };
    }
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.