alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (LongHashMap.java)

This example Java source code file (LongHashMap.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

capacity, concurrentmodificationexception, entry, illegal, illegalargumentexception, initial, load, longhashmap, object, util

The LongHashMap.java Java example source code

/*
 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

package sun.jvm.hotspot.debugger;

import java.util.*;

/**
 * This is a copy of java.util.HashMap which uses longs as keys
 * instead of Objects. It turns out that using this in the PageCache
 * implementation speeds up heap traversals by a factor of three.
 *
 * @author  Josh Bloch
 * @author Arthur van Hoff
 */

public class LongHashMap
{
    static class Entry {
        private int    hash;
        private long   key;
        private Object value;
        private Entry  next;

        Entry(int hash, long key, Object value, Entry next) {
            this.hash  = hash;
            this.key   = key;
            this.value = value;
            this.next  = next;
        }

        /**
         * Returns the key corresponding to this entry.
         *
         * @return the key corresponding to this entry.
         */
        long getKey() { return key; }

        /**
         * Returns the value corresponding to this entry.  If the mapping
         * has been removed from the backing map (by the iterator's
         * <tt>remove operation), the results of this call are undefined.
         *
         * @return the value corresponding to this entry.
         */
        Object getValue() { return value; }

        /**
         * Replaces the value corresponding to this entry with the specified
         * value (optional operation).  (Writes through to the map.)  The
         * behavior of this call is undefined if the mapping has already been
         * removed from the map (by the iterator's <tt>remove operation).
         *
         * @param value new value to be stored in this entry.
         * @return old value corresponding to the entry.
         *
         * @throws UnsupportedOperationException if the <tt>put operation
         *            is not supported by the backing map.
         * @throws ClassCastException if the class of the specified value
         *            prevents it from being stored in the backing map.
         * @throws    IllegalArgumentException if some aspect of this value
         *            prevents it from being stored in the backing map.
         * @throws NullPointerException the backing map does not permit
         *            <tt>null values, and the specified value is
         *            <tt>null.
         */
        Object setValue(Object value) {
            Object oldValue = this.value;
            this.value = value;
            return oldValue;
        }

        /**
         * Compares the specified object with this entry for equality.
         * Returns <tt>true if the given object is also a map entry and
         * the two entries represent the same mapping.  More formally, two
         * entries <tt>e1 and e2 represent the same mapping
         * if<pre>
         *     (e1.getKey()==null ?
         *      e2.getKey()==null : e1.getKey().equals(e2.getKey()))  &&
         *     (e1.getValue()==null ?
         *      e2.getValue()==null : e1.getValue().equals(e2.getValue()))
         * </pre>
         * This ensures that the <tt>equals method works properly across
         * different implementations of the <tt>Map.Entry interface.
         *
         * @param o object to be compared for equality with this map entry.
         * @return <tt>true if the specified object is equal to this map
         *         entry.
         */
        public boolean equals(Object o) {
            if (!(o instanceof Entry))
                return false;
            Entry e = (Entry)o;
            return (key == e.getKey()) && eq(value, e.getValue());
        }

        /**
         * Returns the hash code value for this map entry.  The hash code
         * of a map entry <tt>e is defined to be: 
         *     (e.getKey()==null   ? 0 : e.getKey().hashCode()) ^
         *     (e.getValue()==null ? 0 : e.getValue().hashCode())
         * </pre>
         * This ensures that <tt>e1.equals(e2) implies that
         * <tt>e1.hashCode()==e2.hashCode() for any two Entries
         * <tt>e1 and e2, as required by the general
         * contract of <tt>Object.hashCode.
         *
         * @return the hash code value for this map entry.
         * @see Object#hashCode()
         * @see Object#equals(Object)
         * @see #equals(Object)
         */
        public int hashCode() {
            return hash ^ (value==null ? 0 : value.hashCode());
        }
    }

    /**
     * The hash table data.
     */
    transient Entry table[];

    /**
     * The total number of mappings in the hash table.
     */
    transient int size;

    /**
     * The table is rehashed when its size exceeds this threshold.  (The
     * value of this field is (int)(capacity * loadFactor).)
     *
     * @serial
     */
    int threshold;

    /**
     * The load factor for the hash table.
     *
     * @serial
     */
    final float loadFactor;

    /**
     * The number of times this HashMap has been structurally modified
     * Structural modifications are those that change the number of mappings in
     * the HashMap or otherwise modify its internal structure (e.g.,
     * rehash).  This field is used to make iterators on Collection-views of
     * the HashMap fail-fast.  (See ConcurrentModificationException).
     */
    transient int modCount = 0;

    /**
     * Constructs a new, empty map with the specified initial
     * capacity and the specified load factor.
     *
     * @param      initialCapacity   the initial capacity of the HashMap.
     * @param      loadFactor        the load factor of the HashMap
     * @throws     IllegalArgumentException  if the initial capacity is less
     *               than zero, or if the load factor is nonpositive.
     */
    public LongHashMap(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Initial Capacity: "+
                                               initialCapacity);
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal Load factor: "+
                                               loadFactor);
        if (initialCapacity==0)
            initialCapacity = 1;
        this.loadFactor = loadFactor;
        table = new Entry[initialCapacity];
        threshold = (int)(initialCapacity * loadFactor);
    }

    /**
     * Constructs a new, empty map with the specified initial capacity
     * and default load factor, which is <tt>0.75.
     *
     * @param   initialCapacity   the initial capacity of the HashMap.
     * @throws    IllegalArgumentException if the initial capacity is less
     *              than zero.
     */
    public LongHashMap(int initialCapacity) {
        this(initialCapacity, 0.75f);
    }

    /**
     * Constructs a new, empty map with a default capacity and load
     * factor, which is <tt>0.75.
     */
    public LongHashMap() {
        this(11, 0.75f);
    }

    /**
     * Returns the number of key-value mappings in this map.
     *
     * @return the number of key-value mappings in this map.
     */
    public int size() {
        return size;
    }

    /**
     * Returns <tt>true if this map contains no key-value mappings.
     *
     * @return <tt>true if this map contains no key-value mappings.
     */
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * Returns the value to which this map maps the specified key.  Returns
     * <tt>null if the map contains no mapping for this key.  A return
     * value of <tt>null does not necessarily indicate that the
     * map contains no mapping for the key; it's also possible that the map
     * explicitly maps the key to <tt>null.  The containsKey
     * operation may be used to distinguish these two cases.
     *
     * @return the value to which this map maps the specified key.
     * @param key key whose associated value is to be returned.
     */
    public Object get(long key) {
        Entry e = getEntry(key);
        return (e == null ? null : e.value);
    }

    /**
     * Returns <tt>true if this map contains a mapping for the specified
     * key.
     *
     * @return <tt>true if this map contains a mapping for the specified
     * key.
     * @param key key whose presence in this Map is to be tested.
     */
    public boolean containsKey(long key) {
        return getEntry(key) != null;
    }

    /**
     * Returns the entry associated with the specified key in the
     * HashMap.  Returns null if the HashMap contains no mapping
     * for this key.
     */
    Entry getEntry(long key) {
        Entry tab[] = table;
        int hash = (int) key;
        int index = (hash & 0x7FFFFFFF) % tab.length;

        for (Entry e = tab[index]; e != null; e = e.next)
            if (e.hash == hash && e.key ==key)
                return e;

        return null;
    }

    /**
     * Returns <tt>true if this map maps one or more keys to the
     * specified value.
     *
     * @param value value whose presence in this map is to be tested.
     * @return <tt>true if this map maps one or more keys to the
     *         specified value.
     */
    public boolean containsValue(Object value) {
        Entry tab[] = table;

        if (value==null) {
            for (int i = tab.length ; i-- > 0 ;)
                for (Entry e = tab[i] ; e != null ; e = e.next)
                    if (e.value==null)
                        return true;
        } else {
            for (int i = tab.length ; i-- > 0 ;)
                for (Entry e = tab[i] ; e != null ; e = e.next)
                    if (value.equals(e.value))
                        return true;
        }

        return false;
    }

    /**
     * Associates the specified value with the specified key in this map.
     * If the map previously contained a mapping for this key, the old
     * value is replaced.
     *
     * @param key key with which the specified value is to be associated.
     * @param value value to be associated with the specified key.
     * @return previous value associated with specified key, or <tt>null
     *         if there was no mapping for key.  A <tt>null return can
     *         also indicate that the HashMap previously associated
     *         <tt>null with the specified key.
     */
    public Object put(long key, Object value) {
        Entry tab[] = table;
        int hash = (int) key;
        int index = (hash & 0x7FFFFFFF) % tab.length;

        // Look for entry in hash table
        for (Entry e = tab[index] ; e != null ; e = e.next) {
            if (e.hash == hash && e.key == key) {
                Object oldValue = e.value;
                e.value = value;
                return oldValue;
            }
        }

        // It's not there; grow the hash table if necessary...
        modCount++;
        if (size >= threshold) {
            rehash();
            tab = table;
            index = (hash & 0x7FFFFFFF) % tab.length;
        }

        // ...and add the entry
        size++;
        tab[index] = newEntry(hash, key, value, tab[index]);
        return null;
    }

    /**
     * Removes the mapping for this key from this map if present.
     *
     * @param key key whose mapping is to be removed from the map.
     * @return previous value associated with specified key, or <tt>null
     *         if there was no mapping for key.  A <tt>null return can
     *         also indicate that the map previously associated <tt>null
     *         with the specified key.
     */
    public Object remove(long key) {
        Entry e = removeEntryForKey(key);
        return (e == null ? null : e.value);
    }

    /**
     * Removes and returns the entry associated with the specified key
     * in the HashMap.  Returns null if the HashMap contains no mapping
     * for this key.
     */
    Entry removeEntryForKey(long key) {
        Entry tab[] = table;
        int hash = (int) key;
        int index = (hash & 0x7FFFFFFF) % tab.length;

        for (Entry e = tab[index], prev = null; e != null;
             prev = e, e = e.next) {
            if (e.hash == hash && e.key == key) {
                modCount++;
                if (prev != null)
                    prev.next = e.next;
                else
                    tab[index] = e.next;

                size--;
                return e;
            }
        }

        return null;
    }

    /**
     * Removes the specified entry from this HashMap (and increments modCount).
     *
     * @throws ConcurrentModificationException if the entry is not in the Map
     */
    void removeEntry(Entry doomed) {
        Entry[] tab = table;
        int index = (doomed.hash & 0x7FFFFFFF) % tab.length;

        for (Entry e = tab[index], prev = null; e != null;
             prev = e, e = e.next) {
            if (e == doomed) {
                modCount++;
                if (prev == null)
                    tab[index] = e.next;
                else
                    prev.next = e.next;
                size--;
                return;
            }
        }
        throw new ConcurrentModificationException();
    }

    /**
     * Removes all mappings from this map.
     */
    public void clear() {
        Entry tab[] = table;
        modCount++;
        for (int index = tab.length; --index >= 0; )
            tab[index] = null;
        size = 0;
    }

    /**
     * Rehashes the contents of this map into a new <tt>HashMap instance
     * with a larger capacity. This method is called automatically when the
     * number of keys in this map exceeds its capacity and load factor.
     */
    void rehash() {
        Entry oldTable[] = table;
        int oldCapacity = oldTable.length;
        int newCapacity = oldCapacity * 2 + 1;
        Entry newTable[] = new Entry[newCapacity];

        modCount++;
        threshold = (int)(newCapacity * loadFactor);
        table = newTable;

        for (int i = oldCapacity ; i-- > 0 ;) {
            for (Entry old = oldTable[i] ; old != null ; ) {
                Entry e = old;
                old = old.next;

                int index = (e.hash & 0x7FFFFFFF) % newCapacity;
                e.next = newTable[index];
                newTable[index] = e;
            }
        }
    }

    static boolean eq(Object o1, Object o2) {
        return (o1==null ? o2==null : o1.equals(o2));
    }

    Entry newEntry(int hash, long key, Object value, Entry next) {
        return new Entry(hash, key, value, next);
    }

    int capacity() {
        return table.length;
    }

    float loadFactor() {
        return loadFactor;
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java LongHashMap.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.