The source code of HashMap.values()
is shown as follows
public Collection values() {
Collection vs = values;
return (vs !=
It's a misconception that the Values
class is "of course empty". Just because there is no method called on it and its constructor doesn't have any arguments doesn't mean that the collection is empty.
The Values
class is an "inner class" (a non-static nested class) of HashMap
, which means that it has an implicit reference to the HashMap
object that created it. It can therefore access all elements of the HashMap
, either explicitly by using the HashMap.this
reference or by just accessing the members directly. Since it is an inner class, it is even allowed to access the HashMap
's private members.
You can see that for example in the Values
class' implementation of the size
method:
public int size() {
return size;
}
The Values
class doesn't have a size
member, so that size
refers to the HashMap
's size. It's equivalent to:
public int size() {
return HashMap.this.size;
}
EDIT: Note that this also means that the collection you receive is not a copy, but still refers to the original HashMap
contents and therefore changes when you update the HashMap
:
// Getting the entry set (not a copy!)
Set<Entry<String, String>> entries = map.entrySet();
// Add elements to the map afterwards
map.put("abc", "def");
// Check out the entries in the collection
// (magically containing the elements added after getting the collection)
System.out.println(entries); // "[abc=def]"
The Values
class implements a Collection
that is backed by the HashMap
. As mastov commented, Values
is an inner class of HashMap
, which gives it access to the members of the enclosing HashMap
instance it is associated with. Therefore it's not empty. Its size is the size of the HashMap
, and when you iterate over it, you are iterating over the Entries of the HashMap
.
When you call System.out.println(values);
, you are calling the toString
method of AbstractCollection
, which uses an Iterator
to iterate over the values and get their String
representation. The Iterator
actually iterates over the Entries of the HashMap
and returns their values.
The same goes for the Set
s returned by keySet
and entrySet
.
Collection<V> vs = values;
return (vs != null ? vs : (values = new Values()));
These two line answer your question.
values
is a internal collection (Inherited from AbstractMap
). If it is not null
then it will be returned.
If it is null
then it will be initialized and the new one will returned.
Now I guess, the main point of your question is
when and how do these methods return objects with elements we need?
Technically values
always return this initialized Object. Then how we get our entry values from these object.?
Lets go a little deep:
values() actually return an object of class Values
which is an Inner class of HashMap
and extends AbstractCollection
private final class Values extends AbstractCollection<V>
As you have looked into the source code. Then you will find inside the Values
class
public Iterator<V> iterator() {
return newValueIterator();
}
this newValueIterator()
does the trick.
If you go more deeper you will find newValueIterator()
returns object of ValueIterator
which is a subclass of HashIterator
HashIterator
implements basic functionality for iteration, which actually itterate over the table
maintained by the HashMap
.