Reputation: 107
We can use an entrySet() method to iterate over the hashmap key-value pairs stored in Node[] table field .
HahMap<K,V> hashmap = new HashMap<>() ;
public Set<Map.Entry<K,V>> entrySet()
{
Set<Map.Entry<K,V>> es;
return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;
}
When we use this in a for-each loop like :
for ( Map.Entry<K,V> entry : hashmap.entrySet () )
{
...
// entry is an object of return type Map.Entry and object type Node .
// got the object type by calling entry.getClass() and also no other inner class other than Node implements Map.Entry . ;
}
These objects are stored in a Set . But where is the code which links them to the field table which has key-value pairs .
For example : In toString() method when we get Iterable using iterator() method , and call next() method on Iterable the call goes to nextNode() of HashIterator class where the object returned is linked to table field of HashMap class . But what happens here ? Please help .
Upvotes: 1
Views: 1919
Reputation: 298143
You seem to lack the understanding of what a view is. A view has no stored data, but just fulfills a certain interface by delegating to the actual data object.
A simple example is the list view created via Collections.unmodifiableList(…)
which does not contain any data, but delegates all method calls to the original list, excluding the modification methods, of course.
The entry set fulfills the Set
interface by delegating to the underlying map. Most notably, by returning an Iterator
, as most methods are build upon this, only a few others are overridden for performance, e.g. size()
delegates directly to the map’s size()
. So if it appears as if the entry set contains something, it is, because the iterator reports it during the traversal.
The Hashmap
’s entry set iterator iterates over the internal array of entries, just like the key set iterator and the value collection iterator. The only difference between them is which object they return in the next()
method, the entry set iterator just returns the entry, the other two extract the key resp. value of the entry. That’s why these iterator only override that single method.
Note that this interaction can also be seen the other way round. When you implement a Map
by extending AbstractMap
, the entrySet()
is the only method you need to implement, all other map methods are already implemented via delegation to the entry set. You might override some of them for performance, though. But the question, which actually contains the data, is moot, both, the Map
and the entry Set
are views to the same underlying data.
Maybe the following example helps:
String[][] pairs={ {"foo","bar"}, {"hello","world"} };
Map<String,String> map = new AbstractMap<String, String>() {
public Set<Map.Entry<String, String>> entrySet() {
return new AbstractSet<Entry<String, String>>() {
public Iterator<Map.Entry<String, String>> iterator() {
return Arrays.stream(pairs)
.<Entry<String,String>>map(p -> new SimpleImmutableEntry<>(p[0],p[1]))
.iterator();
}
public int size() {
return pairs.length;
}
};
}
};
System.out.println(map.get("foo"));
System.out.println(map.containsKey("hello"));
System.out.println(map.containsValue("world"));
map.forEach((k,v) -> System.out.println(k+" -> "+v));
System.out.println(map);
It creates an immutable map that is never put into. Still, it reports the intended contents through all Map
methods, just because the entry set iterator reports this content.
Upvotes: 2
Reputation: 120848
If I have not missed anything from your question: EntrySet
overrides iterator
method (making it an Iterable
to be used in forEach) that in turn returns an EntryIterator
- it overrides the next
method:
public final Map.Entry<K,V> next() { return nextNode(); }
But it also extends HashIterator
that defines the hasNext
method.
It is actually as simple as that. But generally these are inner classes - and they have access to everything they might need in the HashMap
class.
Upvotes: 0