views:

356

answers:

4

I have a class MyMap which wraps TreeMap. (Say it's a collection of dogs and that the keys are strings).

public class MyMap {
   private TreeMap<String, Dog> map;
...
}

I would like to turn MyMap iterable with the for-each loop. I know how I would've done it if my class was a LinkedList wrapper:

public class MyList implements Iterable<Dog> {
   private LinkedList<Dog> list;
   ...
   public Iterator<Dog> iterator() {
      return list.iterator();
   }
}

But such a solution doesn't work for TreeMap because TreeMap doesn't have an iterator(). So how can I make MyMap iterable?

And the same question except MyMap wraps HashMap (instead of TreeMap).

Thanks.

+5  A: 

It's because you can only iterate the keys or the values of a Map, not the map itself

Typically you can do this:

for( Object value : mymap.values()  ){
  System.out.println(value);
}

So, what I'm suggesting is: does your Map need to have an iterable? Not if you just want to get at the values... or the keys themselves.

Also, consider using Google's forwarding collections such as ForwardingList

harschware
What do you mean? What I want is to iterate the values of my Map. How can I do that?
snakile
`values().iterator()`
Jonathan Feinberg
I upvoted your one because I think it's a more correct answer than trying to subclass `TreeMap` or the like. However, you can also iterate a map's entries too, which is often the most useful way to iterate through a map.
Chris Jester-Young
You can iterate over K/V pairs easily with `.entrySet()` which returns contents of Map as a list of `Map.Entry<K,V>` :s.
Esko
It's a little odd to see a loop variable called `key` used to iterate over values.
Pete Kirkham
I'm wavering on -1 here, because while it's strictly true that Map does not have an iterator, that answer is misleading
kdgregory
@Pete Kirkham - thanks, corrected.
harschware
My answer was written while poster changed the question... @Jonathan Feinberg's *comment* is actually the better answer at this time.
harschware
Yes, the poster is a moving target, and I'm hovering on a -1 on the question.
Jonathan Feinberg
+4  A: 
public Iterator<Dog> iterator() {
      return map.values().iterator();
}
Jonathan Feinberg
I'm not sure your answer solves my problem. I don't quite understand it. Anyway, I didn't extend TreeMap. TreeMap is a field in my class. I edited my question to make it more clear.
snakile
Well, then, `map.values().iterator()` will give you an iterator over your map's values!
Jonathan Feinberg
@john - OK, then `MyMap` should define an `iterator()` method that returns `_map.entrySet().iterator()`
kdgregory
@Feinberg: What I wanted is the second thing you wrote in your answer. The one with return map.values().iterator(). Please edit your answer to contain only that part (without the exteds TreeMap) and I'll accept it.I still have two questions:1. If I wrap HashMap (instead of TreeMap) will the iterator return the values in the order of the keys?2. It seems to me not efficient to call values() every time I want to iterate my map. Am I right?
snakile
1) No, per the documentation, hashmap keys have no defined order.2) Why would you be creating a new iterator in a tight loop? You're only creating the iterator once each time you want to iterate over the values. There *is* no other way!
Jonathan Feinberg
A: 

One possibility may be to define an entrySet() method that returns a Set and then iterate over the Set.

For-each iteration would look something like this:

for (Map.Entry<String,Integer> m: someMap.entrySet()){
   System.out.println("Key="+m.getKey()+" value="+m.getValue());
}
MAK
+2  A: 
public class MyMap implements Iterable<Dog> {
   private TreeMap<String, Dog> map;
   ...
   @Override
   public Iterator<Dog> iterator() {
      return map.values().iterator();
   }
}

map.values() is a collection view of the dogs contained in map. The collection's iterator will return the values in the order that their corresponding keys appear in the tree. Thanks to Jonathan Feinberg.

snakile
+1 for mentioning the "implements Iterable<Dog>" interface.
I82Much