Getting Started with Java source code analysis Hashtable collection series (xi) the set of Java source code analysis Starter Series Hashtable (XI)

Getting Started with Java source code analysis Hashtable collection series (XI)

 

Foreword

We realized on a hashing algorithm and conflict resolution we used two ways to address law and open chain address law, in this section we analyze in detail the source code, the source code to see which way the conflict is for the use and comparative we have achieved, what place can be modified.

Hashtable source code analysis

We analyze the sample code behind what is new in the console operated by instantiating Hashtable and add the key, as follows:

 public static void main(String[] args) {

        Hashtable hashtable = new Hashtable();
        hashtable.put(-100, "first");
 }

Next we look at when we initialize Hashtable, behind prepared to do what work?

Copy the code
public class Hashtable<K,V>
    extends Dictionary<K,V>
    implements Map<K,V>, Cloneable, java.io.Serializable {

    // storing key data
    private transient Entry<?,?>[] table;

    // size of data storage
    private transient int count;

    // Threshold: (int) (capacity * loadFactor)).
    private int threshold;

    // Load factor: time and space cost tradeoffs default is 0.75. Because although higher value will reduce the space overhead but increase the time to find cost elements
    private float loadFactor;

    // Specify constructor capacity and load factor
    public Hashtable(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal Load: "+loadFactor);

        if (initialCapacity==0)
            initialCapacity = 1;
            
        this.loadFactor = loadFactor;
        
        table = new Entry<?,?>[initialCapacity];
        
        // The default threshold is 8
        threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
    }

   // constructor specified capacity
    public Hashtable(int initialCapacity) {
        this(initialCapacity, 0.75f);
    }

    No // Default constructor parameters (initial capacity of 11, the load factor is 0.75f)
    public Hashtable() {
        this(11, 0.75f);
    }
    
    
    private static class Entry<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        V value;
        Entry<K,V> next;

        protected Entry(int hash, K key, V value, Entry<K,V> next) {
            this.hash = hash;
            this.key =  key;
            this.value = value;
            this.next = next;
        }
    }
}
Copy the code

Internal Entry Hashtable array by storing data, by using the Entry-chain structure may be seen to resolve hash collision address method, when initializing Hashtable capacity and load factor are not specified, the default initial capacity of 11, the load factor is 0.75, the threshold value is 8, if the exception is thrown capacity is less than 0, if the capacity is equal to 0 to 1 and the threshold capacity value of 0 otherwise specified threshold value calculated in the capacity or in a specified capacity * 0.75 * specified load factor calculation prevail. 

We will soon be able to come to the definition above conclusions, this point we do not have too much further discussion, then we look at when we add the above data as key-value pairs, the interior is through how to do it as source code and variables ?

Copy the code
public synchronized V put(K key, V value) {
        if (value == null) {
            throw new NullPointerException();
        }

        Entry<?,?> tab[] = table;

        int hash = key.hashCode();
       
        int index = (hash & 0x7FFFFFFF) % tab.length;
        
        Entry<K,V> entry = (Entry<K,V>)tab[index];
        
        for(; entry != null ; entry = entry.next) {
            if ((entry.hash == hash) && entry.key.equals(key)) {
                V old = entry.value;
                entry.value = value;
                return old;
            }
        }

        addEntry(hash, key, value, index);
        
        return null;
    }    
Copy the code

We analyze step by step, first add an empty value if an exception is thrown, followed by the hash value is added to obtain the key, the focus here, what role the following code fragment is it?

 int index = (hash & 0x7FFFFFFF) % tab.length;

Because the array index can not be negative, so here the logical operation by the hash value of the key conversion and positive, that is, essentially in order to ensure the index is positive, then the  int index = (hash & 0x7FFFFFFF) % tab. length; how to calculate it? 0x7FFFFFFF Binary 1111111111111111111111111111111 is, since it is positive symbol 0 i.e. 01111111111111111111111111111111, and we add to the value of -100, the binary is 11111111111111111111111110011100, converts them to binary logical sum operation, the final result is 01111111111111111111111110011100, to decimal 2147483548 result, which is to explain the principles of our calculation, we actually can by subtracting decimal the decimal 0x7FFFFFFF is 2147483647, then we subtract directly on the basis of (100-1) i.e. 99, finally obtained also 2,147,483,548. Finally, taking the results of the initial capacity of the mold 11 is of index 1. If the key is the hash value is positive then there is no problem, that is, by logical AND operation resulting hash value is the original value. Then I get the position corresponding to the index in the array, and then loop, the question is why does the array cycle? That is, the following code fragment:

Copy the code
       for(; entry != null ; entry = entry.next) {
            if ((entry.hash == hash) && entry.key.equals(key)) {
                V old = entry.value;
                entry.value = value;
                return old;
            }
        }
Copy the code

In order to solve the above is the same as the corresponding key value will be covered, or not understand? We add a line of code in the console as follows:

Copy the code
public static void main(String[] args) {

        Hashtable hashtable = new Hashtable();
        
        hashtable.put(-100, "first");

        hashtable.put(-100, "second");
}
Copy the code

As we add value to cover the keys are -100, by our analysis of the source of the circulation, this time replacing the first value is above the first row second, in other words, when we add the same key and the latter occur the former value, and we can also return worth to know, if the return value is null does not appear to explain the situation covered, otherwise there is a return value, indicating the presence of the same key and the return value is covered. We Hashtable printed out by the data may be obtained, and this point C # Hashtable different operations, when the same bond is present directly thrown.

Foreword

We realized on a hashing algorithm and conflict resolution we used two ways to address law and open chain address law, in this section we analyze in detail the source code, the source code to see which way the conflict is for the use and comparative we have achieved, what place can be modified.

Hashtable source code analysis

We analyze the sample code behind what is new in the console operated by instantiating Hashtable and add the key, as follows:

 public static void main(String[] args) {

        Hashtable hashtable = new Hashtable();
        hashtable.put(-100, "first");
 }

Next we look at when we initialize Hashtable, behind prepared to do what work?

Copy the code
public class Hashtable<K,V>
    extends Dictionary<K,V>
    implements Map<K,V>, Cloneable, java.io.Serializable {

    // storing key data
    private transient Entry<?,?>[] table;

    // size of data storage
    private transient int count;

    // Threshold: (int) (capacity * loadFactor)).
    private int threshold;

    // Load factor: time and space cost tradeoffs default is 0.75. Because although higher value will reduce the space overhead but increase the time to find cost elements
    private float loadFactor;

    // Specify constructor capacity and load factor
    public Hashtable(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal Load: "+loadFactor);

        if (initialCapacity==0)
            initialCapacity = 1;
            
        this.loadFactor = loadFactor;
        
        table = new Entry<?,?>[initialCapacity];
        
        // The default threshold is 8
        threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
    }

   // constructor specified capacity
    public Hashtable(int initialCapacity) {
        this(initialCapacity, 0.75f);
    }

    No // Default constructor parameters (initial capacity of 11, the load factor is 0.75f)
    public Hashtable() {
        this(11, 0.75f);
    }
    
    
    private static class Entry<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        V value;
        Entry<K,V> next;

        protected Entry(int hash, K key, V value, Entry<K,V> next) {
            this.hash = hash;
            this.key =  key;
            this.value = value;
            this.next = next;
        }
    }
}
Copy the code

Internal Entry Hashtable array by storing data, by using the Entry-chain structure may be seen to resolve hash collision address method, when initializing Hashtable capacity and load factor are not specified, the default initial capacity of 11, the load factor is 0.75, the threshold value is 8, if the exception is thrown capacity is less than 0, if the capacity is equal to 0 to 1 and the threshold capacity value of 0 otherwise specified threshold value calculated in the capacity or in a specified capacity * 0.75 * specified load factor calculation prevail. 

We will soon be able to come to the definition above conclusions, this point we do not have too much further discussion, then we look at when we add the above data as key-value pairs, the interior is through how to do it as source code and variables ?

Copy the code
public synchronized V put(K key, V value) {
        if (value == null) {
            throw new NullPointerException();
        }

        Entry<?,?> tab[] = table;

        int hash = key.hashCode();
       
        int index = (hash & 0x7FFFFFFF) % tab.length;
        
        Entry<K,V> entry = (Entry<K,V>)tab[index];
        
        for(; entry != null ; entry = entry.next) {
            if ((entry.hash == hash) && entry.key.equals(key)) {
                V old = entry.value;
                entry.value = value;
                return old;
            }
        }

        addEntry(hash, key, value, index);
        
        return null;
    }    
Copy the code

We analyze step by step, first add an empty value if an exception is thrown, followed by the hash value is added to obtain the key, the focus here, what role the following code fragment is it?

 int index = (hash & 0x7FFFFFFF) % tab.length;

Because the array index can not be negative, so here the logical operation by the hash value of the key conversion and positive, that is, essentially in order to ensure the index is positive, then the  int index = (hash & 0x7FFFFFFF) % tab. length; how to calculate it? 0x7FFFFFFF Binary 1111111111111111111111111111111 is, since it is positive symbol 0 i.e. 01111111111111111111111111111111, and we add to the value of -100, the binary is 11111111111111111111111110011100, converts them to binary logical sum operation, the final result is 01111111111111111111111110011100, to decimal 2147483548 result, which is to explain the principles of our calculation, we actually can by subtracting decimal the decimal 0x7FFFFFFF is 2147483647, then we subtract directly on the basis of (100-1) i.e. 99, finally obtained also 2,147,483,548. Finally, taking the results of the initial capacity of the mold 11 is of index 1. If the key is the hash value is positive then there is no problem, that is, by logical AND operation resulting hash value is the original value. Then I get the position corresponding to the index in the array, and then loop, the question is why does the array cycle? That is, the following code fragment:

Copy the code
       for(; entry != null ; entry = entry.next) {
            if ((entry.hash == hash) && entry.key.equals(key)) {
                V old = entry.value;
                entry.value = value;
                return old;
            }
        }
Copy the code

In order to solve the above is the same as the corresponding key value will be covered, or not understand? We add a line of code in the console as follows:

Copy the code
public static void main(String[] args) {

        Hashtable hashtable = new Hashtable();
        
        hashtable.put(-100, "first");

        hashtable.put(-100, "second");
}
Copy the code

As we add value to cover the keys are -100, by our analysis of the source of the circulation, this time replacing the first value is above the first row second, in other words, when we add the same key and the latter occur the former value, and we can also return worth to know, if the return value is null does not appear to explain the situation covered, otherwise there is a return value, indicating the presence of the same key and the return value is covered. We Hashtable printed out by the data may be obtained, and this point C # Hashtable different operations, when the same bond is present directly thrown.

Guess you like

Origin www.cnblogs.com/dtydd377455/p/11701558.html