Eva
Eva

Reputation: 4720

Custom map entry set - Is it possible?

I am making a class that maps Strings to Integers. I want to be able to get the Integer associated with a particular String and iterate through the entries, which are defined as another class that implements Map.Entry<String, Integer>.

Currently I have this:

public class MyMap implements Iterable<MyEntry> {

private final Map<String, Integer> wrappedMap = 
    new HashMap<String, Integer>();

@Override
public Iterator<MyEntry> iterator() {
    return wrappedMap.entrySet().iterator();
}

    //more methods

}

It's not compiling because of a type mismatch even though MyEntry implements Map.Entry<String, Integer>.

Is there a way to make a custom implementation of Map.Entry? Is there an easier way to do this that I'm overlooking? Thanks in advanced!

Upvotes: 0

Views: 1499

Answers (3)

jdb
jdb

Reputation: 4519

Why not use just a regular map?

Map<String, MyEntry> map = new HashMap<String, MyEntry>();

Then you iterator will be simply this:

Iterator<MyEntry> iter = map.values().iterator();

Upvotes: 2

Mark Robinson
Mark Robinson

Reputation: 3175

It's not compiling because MyEntry is not a part of the hashmap at all. If you want to return a list of MyEntry then you need to copy the data elements into a MyEntry instance and load that into a collection. Which is going to be slow and consume a considerable amount of memory.

It should be:

@Override
public Iterator<Map.Entry<String,Integer>> iterator() {
    return wrappedMap.entrySet().iterator();
}

The call to entrySet() returns a Set which contains the mappings in the hashmap. So the iterator needs to iterate over Entry objects

Upvotes: 2

amalloy
amalloy

Reputation: 92147

Even though MyEntry implements Map.Entry<K,V>, it is not the case that an Iterator<MyEntry> implements Iterator<Map.Entry<K,V>>. For a class like Iterator, that distinction doesn't make intuitive sense to a human being, so let's instead think of a Box<E> class, which has .put(E) and .contains(E) methods. Is a Box<Dinosaur> a subclass of Box<Animal>? You might think so, but that's not the case: in a Box<Animal> it's legal to call .put(someMammal), but in a Box<Dinosaur> that is clearly illegal. Since Box<Dinosaur> can't support all actions that are legal on a Box<Animal>, it is definitely not a subclass and cannot be substituted in at will.

From the compiler's point of view, the same concern might apply to iterators, and so you can't overload .iterator() to return an object which is not an instance of Iterator<K,V>.

Upvotes: 1

Related Questions