简体   繁体   中英

How does a hashmap work if all its keys have the same value?

If I have a hashmap say HashMap<Integer, String> map = new HashMap<>(); If I have all the values eg 1 up to 100 all storing the same object. In memory, will this be 100 instances of that object or 100 pointers to one object.

Why?
Well if you have a map with HashMap<String, Integer> (notice the swap in generics) and the string is a word and the integer is the number of occurrences if I need to pick a word at random however such that it is proportional to the number of its occurences then a quick way would be just to fill an arraylist with the word "cat" 100 times and the rest accordingly (to "convert" the hashmap into an arraylist) and that way when a random number is picked using list.get(i) then its proportional to its occurences.

So this will take as n words * m occurences which means a huge list. So how efficient would it be to use a HashMap instead.

If indeed there will be pointers from the key to the value (when they repeat) then surely the map is a better approach.

After looking in the Map implemetation, Map#put() uses the static class Node<K,V> which is handling references

    static class Node<K,V> implements Map.Entry<K,V> {
    final int hash;
    final K key;
    V value;
    Node<K,V> next;

    Node(int hash, K key, V value, Node<K,V> next) {
        this.hash = hash;
        this.key = key;
        this.value = value;
        this.next = next;
    } 

example:

    final Map<Integer, Point> map = new HashMap<>();

    final Point xPoint = new Point(0, 0);
    map.put(1, xPoint);
    map.put(2, xPoint);
    map.put(3, xPoint);
    System.out.println(map);
    // modify the point
    System.out.println(xPoint);
    xPoint.setX(555);
    System.out.println(xPoint);
    System.out.println(map);

and I gave a try defininf a custom MAp Integer, Point, (custom point)

    Map<Integer, Point> map = new HashMap<>();

    Point xPoint = new Point(0, 0);
    map.put(1, xPoint);
    map.put(2, xPoint);
    map.put(3, xPoint);
    System.out.println(map);
    // modify the point
    System.out.println(xPoint);
    xPoint.setX(555);
    System.out.println(xPoint);
    System.out.println(map);

as you can see, modifing the point will affect the hole map, since all nodes.V are pointing to the same ref.

It seems to me that the two options you are considering are either :

List<String> words = new ArrayList<>();
words.add("cat");
words.add("cat");
...
words.add("cat");

vs.

Map<Integer,String> words = new HashMap<>();
words.put(0,"cat");
words.put(1,"cat");
...
words.put(99,"cat");

Both the List and the Map would contain multiple reference to the same String object ("cat"). The Map would require more memory, though, since it also has to store the keys.

In addition, you have no easy way of obtaining the i 'th String value of the Map for a given random i , since HashMap has no order.

Therefore your List solution is preferable to your suggested Map<Integer,String> alternative.

That said, you could build a more efficient TreeMap that would allow you to get a random String depending on its number of occurrences.

One way I can think of :

TreeMap<Integer,String> map = new TreeMap<>();
map.put(0,"cat");
map.put(100,"dog");

This TreeMap represents 100 occurrences of "cat" and 20 occurrences of "dog". Now, if you draw a random number from 0 to 119, you can easily check whether it lands in the range of "cat" or "dog".

For example, if you draw the number 105, you obtain the corresponding String with :

String randomStr = map.ceilingEntry(105).getValue();

All that remains is to convert the HashMap<String, Integer> containing the number of occurrences to the corresponding TreeMap<Integer, String> :

HashMap<String, Integer> occurrences = ...
TreeMap<Integer, String> map = new TreeMap<>();
int count = 0;
for (Map.Entry<String,Integer> entry : occurrences.entrySet()) {
    map.put (count, entry.getKey());
    count += entry.getValue();
}

Note that I'm using TreeMap instead of HashMap in order to be able to efficiently obtain the entry having the least key greater than or equal to the given key (without having to iterate over all the entries). This is only possible in NavigableMap s.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM