Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

378
LINES

< > BotCompany Repo | #1029374 // LongIntHashMap_IntMemory64 [dev.] - long to int HashMap that works on disk and is 64 bit

JavaX fragment (include)

1  
/*
2  
 * #!
3  
 * loosely based on code from the Ontopia Engine
4  
 * #-
5  
 * Copyright (C) 2001 - 2013 The Ontopia Project
6  
 * #-
7  
 * Licensed under the Apache License, Version 2.0 (the "License");
8  
 * you may not use this file except in compliance with the License.
9  
 * You may obtain a copy of the License at
10  
 * 
11  
 *      http://www.apache.org/licenses/LICENSE-2.0
12  
 * 
13  
 * Unless required by applicable law or agreed to in writing, software
14  
 * distributed under the License is distributed on an "AS IS" BASIS,
15  
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  
 * See the License for the specific language governing permissions and
17  
 * limitations under the License.
18  
 * !#
19  
 */
20  
21  
// Note: Long.MIN_VALUE and Long.MIN_VALUE+1 are not allowed as keys
22  
sclass LongIntHashMap_IntMemory64 extends AbstractMap<Long, Int> {
23  
  final static int INITIAL_SIZE = 3;
24  
  final static double LOAD_FACTOR = 0.6;
25  
26  
  /**
27  
   * When a key is deleted this object is put into the hashtable in
28  
   * its place, so that other entries with the same key (collisions)
29  
   * further down the hashtable are not lost after we delete an object
30  
   * in the collision chain.
31  
   */
32  
  final static long noKey = Long.MIN_VALUE; // null in original code
33  
  final static long deletedKey = Long.MIN_VALUE+1;
34  
35  
  IIntMemory64 mem;
36  
  
37  
  // memory layout:
38  
  // tableSize at 0
39  
  // elements at 2
40  
  // freecells at 4
41  
  // table starts at 6 (long key, int value, ...)
42  
  
43  
  long tableSize;
44  
  long elements;
45  
  long freecells;
46  
  int modCount;
47  
48  
  *() {
49  
    this(INITIAL_SIZE);
50  
  }
51  
52  
  *(int size) {
53  
    keys = (Long[]) new Object[(size==0 ? 1 : size)];
54  
    values = (Int[]) new Object[(size==0 ? 1 : size)];
55  
    elements = 0;
56  
    freecells = tableSize;
57  
    modCount = 0;
58  
  }
59  
60  
  // ===== MAP IMPLEMENTATION =============================================
61  
62  
  /**
63  
   * Returns the number of key/value mappings in this map.
64  
   */
65  
  public synchronized int size() {
66  
    return elements;
67  
  }
68  
  
69  
  /**
70  
   * Returns <tt>true</tt> if this map contains no mappings.
71  
   */
72  
  public synchronized boolean isEmpty() {
73  
    return elements == 0;
74  
  }
75  
76  
  /**
77  
   * Removes all key/value mappings in the map.
78  
   */
79  
  public synchronized void clear() {
80  
    elements = 0;
81  
    for (long ix = 0; ix < tableSize; ix++) {
82  
      setKey(ix, noKey);
83  
      setValue(ix, 0); // just for beauty
84  
    }
85  
    freecells = tableSize;
86  
    modCount++;
87  
  }
88  
  
89  
  long ptr(long i) { ret 6+i*3; }
90  
  
91  
  void setKey(long i, long key) {
92  
    mem.setLong(ptr(i), key);
93  
  }
94  
  
95  
  void setValue(long i, int val) {
96  
    mem.setInt(ptr(i)+2, val);
97  
  }
98  
  
99  
  /**
100  
   * Returns <tt>true</tt> if this map contains the specified key.
101  
   */
102  
  public synchronized boolean containsKey(Object k) {
103  
    return getKey(findKeyIndex(k)) != noKey;
104  
  }
105  
  
106  
  /**
107  
   * Returns <tt>true</tt> if this map contains the specified value.
108  
   */
109  
  public synchronized boolean containsValue(Object v) {
110  
    for (int ix = 0; ix < tableSize; ix++)
111  
      if (tableSizeix] != null && values[ix].equals(v))
112  
        return true;
113  
114  
    return false;
115  
  }
116  
117  
  /**
118  
   * Returns a read-only set view of the map's keys.
119  
   */
120  
  public synchronized Set<Entry<Long, Int>> entrySet() {
121  
    throw new UnsupportedOperationException();
122  
  }
123  
124  
  /**
125  
   * Removes the mapping with key k, if there is one, and returns its
126  
   * value, if there is one, and null if there is none.
127  
   */
128  
  public synchronized Int remove(Object k) {
129  
    int index = findKeyIndex(k);
130  
131  
    // we found the right position, now do the removal
132  
    if (keys[index] != null) {
133  
      // we found the object
134  
135  
      // same problem here as with put
136  
      Int v = values[index];
137  
      keys[index] = (Long) deletedObject;
138  
      values[index] = (Int) deletedObject;
139  
      modCount++;
140  
      elements--;
141  
      return v;
142  
    } else
143  
      // we did not find the key
144  
      return null;
145  
  }
146  
147  
  /**
148  
   * Adds the specified mapping to this map, returning the old value for
149  
   * the mapping, if there was one.
150  
   */
151  
  public synchronized Int put(Long k, Int v) {
152  
    int hash = k.hashCode();
153  
    long index = (hash & 0x7FFFFFFF) % tableSize;
154  
    int offset = 1;
155  
    int deletedix = -1;
156  
    
157  
    // search for the key (continue while !null and !this key)
158  
    while(keys[index] != null &&
159  
          !(keys[index].hashCode() == hash &&
160  
            keys[index].equals(k))) {
161  
162  
      // if there's a deleted mapping here we can put this mapping here,
163  
      // provided it's not in here somewhere else already
164  
      if (keys[index] == deletedObject)
165  
        deletedix = index;
166  
      
167  
      index = ((index + offset) & 0x7FFFFFFF) % tableSize;
168  
      offset = offset*2 + 1;
169  
170  
      if (offset == -1)
171  
        offset = 2;
172  
    }
173  
    
174  
    if (keys[index] == null) { // wasn't present already
175  
      if (deletedix != -1) // reusing a deleted cell
176  
        index = deletedix;
177  
      else
178  
        freecells--;
179  
180  
      modCount++;
181  
      elements++;
182  
183  
      keys[index] = (Long) k;
184  
      values[index] = (Int) v;
185  
      
186  
      // rehash with increased capacity
187  
      if (1 - (freecells / (double) tableSize) > LOAD_FACTOR)
188  
        rehash(tableSize*2 + 1);
189  
      return null;
190  
    } else { // was there already
191  
      modCount++;
192  
      Int oldv = values[index];
193  
      values[index] = (Int) v;
194  
      return oldv;
195  
    }
196  
  }
197  
198  
  /**
199  
   * INTERNAL: Rehashes the hashmap to a bigger size.
200  
   */
201  
  void rehash(int newCapacity) {
202  
    int oldCapacity = tableSize;
203  
    Long[] newKeys = (Long[]) new Object[newCapacity];
204  
    Int[] newValues = (Int[]) new Object[newCapacity];
205  
206  
    for (int ix = 0; ix < oldCapacity; ix++) {
207  
      Object k = keys[ix];
208  
      if (k == null || k == deletedObject)
209  
        continue;
210  
      
211  
      int hash = k.hashCode();
212  
      int index = (hash & 0x7FFFFFFF) % newCapacity;
213  
      int offset = 1;
214  
215  
      // search for the key
216  
      while(newKeys[index] != null) { // no need to test for duplicates
217  
        index = ((index + offset) & 0x7FFFFFFF) % newCapacity;
218  
        offset = offset*2 + 1;
219  
220  
        if (offset == -1)
221  
          offset = 2;
222  
      }
223  
224  
      newKeys[index] = (Long) k;
225  
      newValues[index] = values[ix];
226  
    }
227  
228  
    keys = newKeys;
229  
    values = newValues;
230  
    freecells = tableSize - elements;
231  
  }
232  
233  
  /**
234  
   * Returns the value for the key k, if there is one, and null if
235  
   * there is none.
236  
   */
237  
  public synchronized Int get(Object k) {
238  
    return values[findKeyIndex(k)];
239  
  }
240  
241  
  /**
242  
   * Returns a virtual read-only collection containing all the values
243  
   * in the map.
244  
   */
245  
  public synchronized Collection<Int> values() {
246  
    return new ValueCollection();
247  
  }
248  
249  
  /**
250  
   * Returns a virtual read-only set of all the keys in the map.
251  
   */
252  
  public synchronized Set<Long> keySet() {
253  
    return new KeySet();
254  
  }
255  
256  
  // --- Internal utilities
257  
258  
  final int findKeyIndex(Object k) {
259  
    if (k == null)
260  
      k = nullObject;
261  
262  
    int hash = k.hashCode();
263  
    int index = (hash & 0x7FFFFFFF) % tableSize;
264  
    int offset = 1;
265  
266  
    // search for the key (continue while !null and !this key)
267  
    while(keys[index] != null &&
268  
          !(keys[index].hashCode() == hash &&
269  
            keys[index].equals(k))) {
270  
      index = ((index + offset) & 0x7FFFFFFF) % tableSize;
271  
      offset = offset*2 + 1;
272  
273  
      if (offset == -1)
274  
        offset = 2;
275  
    }
276  
    return index;
277  
  }
278  
  
279  
  // --- Key set
280  
281  
  class KeySet<Long> extends AbstractSet<Long> {
282  
    public synchronized int size() {
283  
      return elements;
284  
    }
285  
286  
    public synchronized boolean contains(Object k) {
287  
      return containsKey(k);
288  
    }
289  
290  
    public synchronized Iterator<Long> iterator() {
291  
      return new KeyIterator();
292  
    }
293  
  }
294  
295  
  class KeyIterator<Long> implements Iterator<Long> {
296  
    private int ix;
297  
    
298  
    private KeyIterator() {
299  
      // walk up to first value, so that hasNext() and next() return
300  
      // correct results
301  
      for (; ix < tableSize; ix++)
302  
        if (values[ix] != null && keys[ix] != deletedObject)
303  
          break;
304  
    }
305  
306  
    public synchronized boolean hasNext() {
307  
      return ix < tableSize;
308  
    }
309  
310  
    public synchronized void remove() {
311  
      throw new UnsupportedOperationException("Collection is read-only");
312  
    }
313  
314  
    public synchronized Long next() {
315  
      if (ix >= tableSize)
316  
        throw new NoSuchElementException();
317  
      Long key = (Long) keys[ix++];
318  
      
319  
      // walk up to next value
320  
      for (; ix < tableSize; ix++)
321  
        if (keys[ix] != null && keys[ix] != deletedObject)
322  
          break;
323  
      
324  
      // ix now either points to next key, or outside array (if no next)
325  
      return key;
326  
    }
327  
  }
328  
  
329  
  // --- Value collection
330  
331  
  class ValueCollection<Int> extends AbstractCollection<Int> {
332  
    public synchronized int size() {
333  
      return elements;
334  
    }
335  
336  
    public synchronized Iterator<Int> iterator() {
337  
      return new ValueIterator();
338  
    }
339  
340  
    public synchronized boolean contains(Object v) {
341  
      return containsValue(v);
342  
    }
343  
  }
344  
345  
  class ValueIterator<Int> implements Iterator<Int> {
346  
    private int ix;
347  
    
348  
    private ValueIterator() {
349  
      // walk up to first value, so that hasNext() and next() return
350  
      // correct results
351  
      for (; ix < tableSize; ix++)
352  
        if (getKey(ix) != noKey && getKey(ix) != deletedKey)
353  
          break;
354  
    }
355  
356  
    public synchronized boolean hasNext() {
357  
      return ix < tableSize;
358  
    }
359  
360  
    public synchronized void remove() {
361  
      throw new UnsupportedOperationException("Collection is read-only");
362  
    }
363  
364  
    public synchronized Int next() {
365  
      if (ix >= tableSize)
366  
        throw new NoSuchElementException();
367  
      int value = getValue(ix++);
368  
      
369  
      // walk up to next value
370  
      for (; ix < tableSize; ix++)
371  
        if (getKey(ix) != noKey && getKey(ix) != deletedKey)
372  
          break;
373  
      
374  
      // ix now either points to next value, or outside array (if no next)
375  
      return value;
376  
    }
377  
  }
378  
}

Author comment

Began life as a copy of #1013303

download  show line numbers  debug dex  old transpilations   

Travelled to 7 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt, xrpafgyirdlv

No comments. add comment

Snippet ID: #1029374
Snippet name: LongIntHashMap_IntMemory64 [dev.] - long to int HashMap that works on disk and is 64 bit
Eternal ID of this version: #1029374/5
Text MD5: 713a9d81dc3f9df5f50349e4b990cf5e
Author: stefan
Category: javax / collections
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2020-08-03 01:26:55
Source code size: 10070 bytes / 378 lines
Pitched / IR pitched: No / No
Views / Downloads: 202 / 243
Version history: 4 change(s)
Referenced in: [show references]