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

322
LINES

< > BotCompany Repo | #1029376 // LongIntHashMap_IntMemory [dev.] - long to int HashMap that works on disk

JavaX fragment (include) [tags: use-pretranspiled]

Libraryless. Click here for Pure Java version (3053L/19K).

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_IntMemory 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  
  IIntMemory mem;
36  
  
37  
  // memory layout:
38  
  // tableSize at 0
39  
  // elements at 1
40  
  // freecells at 2
41  
  // table starts at 3 (long key, int value, ...)
42  
  
43  
  int tableSize;
44  
  int elements;
45  
  int freecells;
46  
  int modCount;
47  
  
48  
  // load existing map
49  
  *(IIntMemory *mem) {
50  
    tableSize = mem.get(0);
51  
    elements = mem.get(1);
52  
    freecells = mem.get(2);
53  
  }
54  
55  
  // make new map
56  
  *(IIntMemory *mem, int capacity) {
57  
    int tsize = iceil_safe(capacity/LOAD_FACTOR);
58  
    mem.ensureSize(toInt(3+tsize*3L));
59  
    setTableSize(tsize);
60  
    setElements(0);
61  
    setFreecells(tsize);
62  
    for i to tableSize:
63  
      setKey(i, noKey);
64  
  }
65  
  
66  
  void setTableSize(int tableSize) {
67  
    mem.set(0, this.tableSize = tableSize);
68  
  }
69  
70  
  void setElements(int elements) {
71  
    mem.set(1, this.elements = elements);
72  
  }
73  
74  
  void setFreecells(int freecells) {
75  
    mem.set(2, this.freecells = freecells);
76  
  }
77  
78  
  // ===== MAP IMPLEMENTATION =============================================
79  
80  
  public synchronized int size() { ret elements; }
81  
  public synchronized boolean isEmpty() { ret elements == 0; }
82  
83  
  public synchronized void clear() {
84  
    setElements(0);
85  
    for ix to tableSize: {
86  
      setKey(ix, noKey);
87  
      setValue(ix, 0); // just for beauty
88  
    }
89  
    setFreecells(tableSize);
90  
    modCount++;
91  
  }
92  
  
93  
  int ptr(int i) { ret 3+i*3; }
94  
  
95  
  void setKey(int i, long key) {
96  
    mem.setLong(ptr(i), key);
97  
  }
98  
  
99  
  void setValue(int i, int val) {
100  
    mem.set(ptr(i)+2, val);
101  
  }
102  
  
103  
  long getKey(int i) {
104  
    ret mem.getLong(ptr(i));
105  
  }
106  
  
107  
  int getValue(int i) {
108  
    ret mem.get(ptr(i)+2);
109  
  }
110  
  
111  
  public synchronized bool containsKey(Object k) {
112  
    return getKey(findKeyIndex((Long) k)) != noKey;
113  
  }
114  
  
115  
  public synchronized Set<Entry<Long, Int>> entrySet() {
116  
    throw new UnsupportedOperationException();
117  
  }
118  
119  
  public synchronized Int remove(Object k) {
120  
    int index = findKeyIndex((Long) k);
121  
122  
    // we found the right position, now do the removal
123  
    if (getKey(index) != noKey) {
124  
      // we found the object
125  
126  
      // same problem here as with put
127  
      int v = getValue(index);
128  
      setKey(index, deletedKey);
129  
      setValue(index, 0);
130  
      modCount++;
131  
      setElements(elements-1);
132  
      ret v;
133  
    }
134  
    
135  
    // we did not find the key
136  
    null;
137  
  }
138  
139  
  public synchronized Int put(Long k, Int v) {
140  
    int hash = k.hashCode();
141  
    int index = (hash & 0x7FFFFFFF) % tableSize;
142  
    int offset = 1;
143  
    int deletedix = -1;
144  
    
145  
    // search for the key (continue while !null and !this key)
146  
    while (getKey(index) != noKey && getKey(index) != k) {
147  
148  
      // if there's a deleted mapping here we can put this mapping here,
149  
      // provided it's not in here somewhere else already
150  
      if (getKey(index) == deletedKey)
151  
        deletedix = index;
152  
      
153  
      index = ((index + offset) & 0x7FFFFFFF) % tableSize;
154  
      offset = offset*2 + 1;
155  
156  
      if (offset == -1)
157  
        offset = 2;
158  
    }
159  
    
160  
    if (getKey(index) == noKey) { // wasn't present already
161  
      if (deletedix != -1) // reusing a deleted cell
162  
        index = deletedix;
163  
      else
164  
        setFreecells(freecells-1);
165  
166  
      modCount++;
167  
      setElements(elements+1);
168  
169  
      setKey(index, k);
170  
      setValue(index, v);
171  
      
172  
      // rehash with increased capacity
173  
      if (1 - (freecells / (double) tableSize) > LOAD_FACTOR)
174  
        rehash(tableSize*2 + 1);
175  
      null;
176  
    } else { // was there already
177  
      modCount++;
178  
      int oldv = getValue(index);
179  
      setValue(index, v);
180  
      ret oldv;
181  
    }
182  
  }
183  
184  
  /**
185  
   * INTERNAL: Rehashes the hashmap to a bigger size.
186  
   */
187  
  void rehash(int newCapacity) {
188  
    fail("rehash not implemented");
189  
  }
190  
191  
  public synchronized Int get(Object k) {
192  
    int i = findKeyIndex((Long) k);
193  
    ret getKey(i) == noKey ? null : getValue(i);
194  
  }
195  
196  
  public synchronized Collection<Int> values() {
197  
    return new ValueCollection();
198  
  }
199  
200  
  /**
201  
   * Returns a virtual read-only set of all the keys in the map.
202  
   */
203  
  public synchronized Set<Long> keySet() {
204  
    return new KeySet();
205  
  }
206  
207  
  // --- Internal utilities
208  
209  
  final int findKeyIndex(long k) {
210  
    int hash = Long.hashCode(k);
211  
    int index = (hash & 0x7FFFFFFF) % tableSize;
212  
    int offset = 1;
213  
214  
    // search for the key (continue while !null and !this key)
215  
    while (getKey(index) != noKey && getKey(index) != k) {
216  
      index = ((index + offset) & 0x7FFFFFFF) % tableSize;
217  
      offset = offset*2 + 1;
218  
219  
      if (offset == -1)
220  
        offset = 2;
221  
    }
222  
    ret index;
223  
  }
224  
  
225  
  class KeySet extends AbstractSet<Long> {
226  
    public synchronized int size() {
227  
      return elements;
228  
    }
229  
230  
    public synchronized boolean contains(Object k) {
231  
      return containsKey(k);
232  
    }
233  
234  
    public synchronized Iterator<Long> iterator() {
235  
      return new KeyIterator();
236  
    }
237  
  }
238  
239  
  class KeyIterator implements Iterator<Long> {
240  
    private int ix;
241  
    
242  
    private KeyIterator() {
243  
      // walk up to first value, so that hasNext() and next() return
244  
      // correct results
245  
      for (; ix < tableSize; ix++)
246  
        if (getKey(ix) != noKey && getKey(ix) != deletedKey)
247  
          break;
248  
    }
249  
250  
    public synchronized boolean hasNext() {
251  
      return ix < tableSize;
252  
    }
253  
254  
    public synchronized void remove() {
255  
      throw new UnsupportedOperationException("Collection is read-only");
256  
    }
257  
258  
    public synchronized Long next() {
259  
      if (ix >= tableSize)
260  
        throw new NoSuchElementException();
261  
      long key = getKey(ix++);
262  
      
263  
      // walk up to next value
264  
      for (; ix < tableSize; ix++)
265  
        if (getKey(ix) != noKey && getKey(ix) != deletedKey)
266  
          break;
267  
      
268  
      // ix now either points to next key, or outside array (if no next)
269  
      ret key;
270  
    }
271  
  }
272  
  
273  
  // --- Value collection
274  
275  
  class ValueCollection extends AbstractCollection<Int> {
276  
    public synchronized int size() {
277  
      return elements;
278  
    }
279  
280  
    public synchronized Iterator<Int> iterator() {
281  
      return new ValueIterator();
282  
    }
283  
284  
    public synchronized boolean contains(Object v) {
285  
      return containsValue(v);
286  
    }
287  
  }
288  
289  
  class ValueIterator implements Iterator<Int> {
290  
    private int ix;
291  
    
292  
    private ValueIterator() {
293  
      // walk up to first value, so that hasNext() and next() return
294  
      // correct results
295  
      for (; ix < tableSize; ix++)
296  
        if (getKey(ix) != noKey && getKey(ix) != deletedKey)
297  
          break;
298  
    }
299  
300  
    public synchronized boolean hasNext() {
301  
      return ix < tableSize;
302  
    }
303  
304  
    public synchronized void remove() {
305  
      throw new UnsupportedOperationException("Collection is read-only");
306  
    }
307  
308  
    public synchronized Int next() {
309  
      if (ix >= tableSize)
310  
        throw new NoSuchElementException();
311  
      int value = getValue(ix++);
312  
      
313  
      // walk up to next value
314  
      for (; ix < tableSize; ix++)
315  
        if (getKey(ix) != noKey && getKey(ix) != deletedKey)
316  
          break;
317  
      
318  
      // ix now either points to next value, or outside array (if no next)
319  
      return value;
320  
    }
321  
  }
322  
}

Author comment

Began life as a copy of #1029374

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: #1029376
Snippet name: LongIntHashMap_IntMemory [dev.] - long to int HashMap that works on disk
Eternal ID of this version: #1029376/13
Text MD5: ccda07b372ce1503204ed6e42d75e761
Transpilation MD5: f5bd477c5067be2553a229707b260b14
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 21:45:05
Source code size: 8493 bytes / 322 lines
Pitched / IR pitched: No / No
Views / Downloads: 328 / 638
Version history: 12 change(s)
Referenced in: [show references]