001 /*
002 * HashMapLong.java
003 *
004 * Copyright (c) 2001, The University of Sheffield.
005 *
006 * This file is part of GATE (see http://gate.ac.uk/), and is free
007 * software, licenced under the GNU Library General Public License,
008 * Version 2, June 1991 (in the distribution as file licence.html,
009 * and also available at http://gate.ac.uk/gate/licence.html).
010 *
011 * D.Ognyanoff, 15/Nov/2001
012 *
013 */
014
015 package gate.util;
016
017 /**
018 * simple cut-off version of the hashmap with native long's as keys
019 * only get,put and isEmpty methods are implemented().
020 * This map is used in very private case in the SimpleSortedSet class.
021 * The main purpose is to optimize the speed of the SinglePhaseTransducer.transduce()
022 */
023
024 public class HashMapLong {
025
026 /**
027 * The hash table data.
028 */
029 private transient Entry table[];
030
031 private transient int count;
032
033 private int threshold;
034
035 private float loadFactor;
036
037 /**
038 * the main constructor. see the HashMap constructor for description
039 */
040 public HashMapLong(int initialCapacity, float loadFactor) {
041 if (initialCapacity < 0)
042 throw new IllegalArgumentException("Illegal Initial Capacity: "+
043 initialCapacity);
044 if (loadFactor <= 0 || Float.isNaN(loadFactor))
045 throw new IllegalArgumentException("Illegal Load factor: "+
046 loadFactor);
047 if (initialCapacity==0)
048 initialCapacity = 1;
049 this.loadFactor = loadFactor;
050 table = new Entry[initialCapacity];
051 threshold = (int)(initialCapacity * loadFactor);
052 }
053
054 public HashMapLong(int initialCapacity) {
055 this(initialCapacity, 0.75f);
056 }
057
058 public HashMapLong() {
059 this(11, 0.75f);
060 }
061
062 public boolean isEmpty() {
063 return count == 0;
064 }
065
066 public Object get(long key) {
067 Entry tab[] = table;
068 int hash = (int)(key ^ (key >> 32));
069 int index = (hash & 0x7FFFFFFF) % tab.length;
070 for (Entry e = tab[index]; e != null; e = e.next)
071 if ((e.hash == hash) && key == e.key)
072 return e.value;
073
074 return null;
075 }
076
077 /**
078 * Rehashes the contents of this map into a new <tt>HashMapLong</tt> instance
079 * with a larger capacity. This method is called automatically when the
080 * number of keys in this map exceeds its capacity and load factor.
081 */
082 private void rehash() {
083 int oldCapacity = table.length;
084 Entry oldMap[] = table;
085
086 int newCapacity = oldCapacity * 2 + 1;
087 Entry newMap[] = new Entry[newCapacity];
088
089 threshold = (int) (newCapacity * loadFactor);
090 table = newMap;
091
092 for (int i = oldCapacity; i-- > 0; ) {
093 for (Entry old = oldMap[i]; old != null; ) {
094 Entry e = old;
095 old = old.next;
096
097 int index = (e.hash & 0x7FFFFFFF) % newCapacity;
098 e.next = newMap[index];
099 newMap[index] = e;
100 }
101 }
102 }
103
104 public Object put(long key, Object value) {
105 // Makes sure the key is not already in the HashMapLong.
106 Entry tab[] = table;
107 int hash = (int)(key ^ (key >> 32));
108 int index = (hash & 0x7FFFFFFF) % tab.length;
109
110 for (Entry e = tab[index] ; e != null ; e = e.next) {
111 if ((e.hash == hash) && key == e.key) {
112 Object old = e.value;
113 e.value = value;
114 return old;
115 }
116 }
117
118 if (count >= threshold) {
119 // Rehash the table if the threshold is exceeded
120 rehash();
121
122 tab = table;
123 index = (hash & 0x7FFFFFFF) % tab.length;
124 }
125
126 // Creates the new entry.
127 Entry e = new Entry(hash, key, value, tab[index]);
128 tab[index] = e;
129 count++;
130 return null;
131 }
132
133 /**
134 * HashMapLong collision list entry.
135 */
136 private static class Entry {
137 int hash;
138 long key;
139 Object value;
140 Entry next;
141
142 Entry(int hash, long key, Object value, Entry next) {
143 this.hash = hash;
144 this.key = key;
145 this.value = value;
146 this.next = next;
147 }
148 } //Entry
149 } // hasnMapLong
|