The principle analysis of HashMap in Java _java

Source: Internet
Author: User
Tags abs int size static class

Let's take a look at this interview question first:

A series of key-value pairs stored in HashMap, where the key is one of our custom types. After placing the HASHMAP, we change the properties of a key on the outside, and then we use the key to remove the element from the HashMap, what will HashMap return?

The example code and the answer have been presented, but the principle of hashmap is not explained.

1. Characteristics

We can use any class as a HashMap key, but what are the restrictions for these classes? And look at the following code:

public class Person {
  private String name;

  Public person (String name) {
    this.name = name;
  }
}

Map<person, string> testmap = new hashmap<> ();
Testmap.put (New person ("Hello"), "World");
Testmap.get (New person ("Hello")); ---> Null

You want to remove the value of the person class with the same field value, but the result is null. People who know a little about hashmap see that the--person class does not have override Hashcode method, which causes it to inherit the Hashcode of object (the return is its memory address). This is why common invariant classes such as String (or integer) are used as HashMap key. So how does HashMap use Hashcode to quickly index key?

2. Principle

First, let's look at a simple hashmap implementation in "Thinking in Java":

: Containers/simplehashmap.java//A demonstration hashed Map.
Import java.util.*;

Import net.mindview.util.*; public class Simplehashmap<k,v> extends abstractmap<k,v> {//Choose a prime number for the hash table size,
 To achieve a uniform distribution:static final int SIZE = 997; Can ' t have a physical array of generics, but can upcast to one: @SuppressWarnings ("unchecked") linkedlist<
 mapentry<k,v>>[] Buckets = new Linkedlist[size];
  Public V-Put (K key, V value) {V oldValue = null;
  int index = Math.Abs (Key.hashcode ())% SIZE;
  if (buckets[index] = = null) Buckets[index] = new linkedlist<mapentry<k,v>> ();
  Linkedlist<mapentry<k,v>> bucket = Buckets[index];
  Mapentry<k,v> pair = new mapentry<k,v> (key, value);
  Boolean found = false;
  Listiterator<mapentry<k,v>> it = Bucket.listiterator ();
   while (It.hasnext ()) {mapentry<k,v> Ipair = It.next (); if (Ipair.getkey (). Equals (kEY)) {oldValue = Ipair.getvalue (); It.set (pair);
    Replace old with new found = true;
   Break
  } if (!found) buckets[index].add (pair);
 return oldValue;
  Public V get (Object key) {int index = Math.Abs (Key.hashcode ())% SIZE;
  if (buckets[index] = = NULL) return null;
  For (mapentry<k,v> Ipair:buckets[index]) if (Ipair.getkey (). Equals (key)) return Ipair.getvalue ();
 return null; Public set<map.entry<k,v>> EntrySet () {set<map.entry<k,v>> set= new hashset<map.entry&lt ;
  K,v>> ();
   for (linkedlist<mapentry<k,v>> bucket:buckets) {if (bucket = null) continue;
  for (mapentry<k,v> mpair:bucket) Set.add (Mpair);
 return set; public static void Main (string[] args) {simplehashmap<string,string> m = new simplehashmap<string,string
  > ();
  M.putall (Countries.capitals (25));
  System.out.println (m);
  System.out.println (M.get ("Eritrea")); System.out.println (M.ENtryset ());

 }
}

Simplehashmap constructs a hash table to store the Key,hash function is the modulo operation Math.Abs (Key.hashcode ())% SIZE, uses the link table method to solve the hash conflict Each slot of the buckets corresponds to a map.entry with the same (hash) index value, as shown in the following figure:

The HashMap implementation of JDK is similar to that of a hash table storage map.entry with a chain address:

/**
 * The table, resized as necessary. Length must Always is a power of two.
 * *
transient entry<k,v>[] table = (entry<k,v>[]) empty_table;

Static Class Entry<k,v> implements Map.entry<k,v> {
  final K key;
  V value;
  Entry<k,v> Next;
  int hash;
  ..
}

The index of Map.entry is the hash of the key hashcode. When you want the value of the Get key, the index is computed for the key, and then the map.entry is taken out of the table, as in the code:

Public V get (Object key) {
  if (key = null) return
    getfornullkey ();
  entry<k,v> Entry = Getentry (key);

  return NULL = = entry? Null:entry.getValue ();
}

Final entry<k,v> getentry (Object key) {
  if (size = = 0) {return
    null;
  }

  int hash = (key = null)? 0:hash (key);
  for (entry<k,v> e = table[indexfor (hash, table.length)];
     e!= null;
     E = e.next) {
    Object k;
    if (E.hash = = Hash &&
      (k = e.key) = = Key | | (Key!= null && key.equals (k)
      )) return e;
  }
  return null;
}

It is obvious that hashcode directly affects the efficiency of the hash function of HashMap-good hashcode can greatly reduce the hash conflict and improve the query performance. At the same time, this explains the two questions that were raised at the beginning: if the custom class does HashMap key, the hashcode calculation should cover all the fields of the constructor, or it might get null.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.