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

332
LINES

< > BotCompany Repo | #1012720 // WeakCompactHashSet (all in one object, abandoned attempt)

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

Transpiled version (3757L) is out of date.

1  
/*
2  
 * #!
3  
 * 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  
// modified by Stefan Reich
22  
23  
sclass WeakCompactHashSet<A> extends java.util.AbstractSet<A> {
24  
  protected final static int INITIAL_SIZE = 3;
25  
  protected final static double LOAD_FACTOR = 0.75;
26  
27  
  protected final static WeakReference nullObject = new WeakReference(null);
28  
  protected final static WeakReference deletedObject = new WeakReference(null);
29  
  protected int elements;
30  
  protected int freecells;
31  
  protected MyWeakReference<A>[] objects;
32  
  protected int modCount;
33  
  
34  
  sclass MyWeakReference<A> extends WeakReference<A> {
35  
    int hash;
36  
    
37  
    public int hashCode() { ret hash; }
38  
  }
39  
  
40  
  *() {
41  
    this(INITIAL_SIZE);
42  
  }
43  
44  
  *(int size) {
45  
    // NOTE: If array size is 0, we get a
46  
    // "java.lang.ArithmeticException: / by zero" in add(Object).
47  
    objects = new WeakReference[(size==0 ? 1 : size)];
48  
    elements = 0;
49  
    freecells = objects.length;
50  
    modCount = 0;
51  
  }
52  
53  
  *(Collection<A> c) {
54  
    this(c.size());
55  
    addAll(c);
56  
  }
57  
58  
  @Override
59  
  public Iterator<A> iterator() {
60  
    return new CompactHashIterator<A>();
61  
  }
62  
63  
  @Override
64  
  public int size() {
65  
    return elements;
66  
  }
67  
68  
  @Override
69  
  public boolean isEmpty() {
70  
    return elements == 0;
71  
  }
72  
73  
  @Override
74  
  public boolean contains(Object o) {
75  
    ret find(o) != null;
76  
  }
77  
  
78  
  synchronized A find(O o) {
79  
    if (o == null) o = nullObject;
80  
    
81  
    int hash = o.hashCode();
82  
    int index = (hash & 0x7FFFFFFF) % objects.length;
83  
    int offset = 1;
84  
85  
    // search for the object (continue while !null and !this object)
86  
    while(objects[index] != null &&
87  
          !(objects[index].hashCode() == hash &&
88  
            objects[index].equals(o))) {
89  
      index = ((index + offset) & 0x7FFFFFFF) % objects.length;
90  
      offset = offset*2 + 1;
91  
92  
      if (offset == -1)
93  
        offset = 2;
94  
    }
95  
96  
    ret objects[index];
97  
  }
98  
99  
  @Override
100  
  synchronized public boolean add(Object o) {
101  
    if (o == null) o = nullObject;
102  
103  
    int hash = o.hashCode();
104  
    int index = (hash & 0x7FFFFFFF) % objects.length;
105  
    int offset = 1;
106  
    int deletedix = -1;
107  
    
108  
    // search for the object (continue while !null and !this object)
109  
    while(objects[index] != null &&
110  
          !(objects[index].hashCode() == hash &&
111  
            objects[index].equals(o))) {
112  
113  
      // if there's a deleted object here we can put this object here,
114  
      // provided it's not in here somewhere else already
115  
      if (objects[index] == deletedObject)
116  
        deletedix = index;
117  
      
118  
      index = ((index + offset) & 0x7FFFFFFF) % objects.length;
119  
      offset = offset*2 + 1;
120  
121  
      if (offset == -1)
122  
        offset = 2;
123  
    }
124  
    
125  
    if (objects[index] == null) { // wasn't present already
126  
      if (deletedix != -1) // reusing a deleted cell
127  
        index = deletedix;
128  
      else
129  
        freecells--;
130  
131  
      modCount++;
132  
      elements++;
133  
134  
      // here we face a problem regarding generics:
135  
      // add(A o) is not possible because of the null Object. We cant do 'new A()' or '(A) new Object()'
136  
      // so adding an empty object is a problem here
137  
      // If (! o instanceof A) : This will cause a class cast exception
138  
      // If (o instanceof A) : This will work fine
139  
140  
      objects[index] = (A) o;
141  
      
142  
      // do we need to rehash?
143  
      if (1 - (freecells / (double) objects.length) > LOAD_FACTOR)
144  
        rehash();
145  
      return true;
146  
    } else // was there already 
147  
      return false;
148  
  }
149  
  
150  
  @Override
151  
  synchronized public boolean remove(Object o) {
152  
    if (o == null) o = nullObject;
153  
    
154  
    int hash = o.hashCode();
155  
    int index = (hash & 0x7FFFFFFF) % objects.length;
156  
    int offset = 1;
157  
    
158  
    // search for the object (continue while !null and !this object)
159  
    while(objects[index] != null &&
160  
          !(objects[index].hashCode() == hash &&
161  
            objects[index].equals(o))) {
162  
      index = ((index + offset) & 0x7FFFFFFF) % objects.length;
163  
      offset = offset*2 + 1;
164  
165  
      if (offset == -1)
166  
        offset = 2;
167  
    }
168  
169  
    // we found the right position, now do the removal
170  
    if (objects[index] != null) {
171  
      // we found the object
172  
173  
      // same problem here as with add
174  
      objects[index] = (A) deletedObject;
175  
      modCount++;
176  
      elements--;
177  
      return true;
178  
    } else
179  
      // we did not find the object
180  
      return false;
181  
  }
182  
  
183  
  @Override
184  
  synchronized public void clear() {
185  
    elements = 0;
186  
    for (int ix = 0; ix < objects.length; ix++)
187  
      objects[ix] = null;
188  
    freecells = objects.length;
189  
    modCount++;
190  
  }
191  
192  
  @Override
193  
  synchronized public Object[] toArray() {
194  
    Object[] result = new Object[elements];
195  
    Object[] objects = this.objects;
196  
    int pos = 0;
197  
    for (int i = 0; i < objects.length; i++)
198  
      if (objects[i] != null && objects[i] != deletedObject) {
199  
        if (objects[i] == nullObject)
200  
          result[pos++] = null;
201  
        else
202  
          result[pos++] = objects[i];
203  
      }
204  
    // unchecked because it should only contain A
205  
    return result;
206  
  }
207  
208  
  // not sure if this needs to have generics
209  
  @Override
210  
  synchronized public <T> T[] toArray(T[] a) {
211  
    int size = elements;
212  
    if (a.length < size)
213  
      a = (T[])java.lang.reflect.Array.newInstance(
214  
                                 a.getClass().getComponentType(), size);
215  
    A[] objects = this.objects;
216  
    int pos = 0;
217  
    for (int i = 0; i < objects.length; i++)
218  
      if (objects[i] != null && objects[i] != deletedObject) {
219  
        if (objects[i] == nullObject)
220  
          a[pos++] = null;
221  
        else
222  
          a[pos++] = (T) objects[i];
223  
      }
224  
    return a;
225  
  }
226  
  
227  
  protected void rehash() {
228  
    int gargagecells = objects.length - (elements + freecells);
229  
    if (gargagecells / (double) objects.length > 0.05)
230  
      // rehash with same size
231  
      rehash(objects.length);
232  
    else
233  
      // rehash with increased capacity
234  
      rehash(objects.length*2 + 1);
235  
  }
236  
  
237  
  protected void rehash(int newCapacity) {
238  
    int oldCapacity = objects.length;
239  
    @SuppressWarnings("unchecked")
240  
    WeakReference<A>[] newObjects = new WeakReference[newCapacity];
241  
242  
    for (int ix = 0; ix < oldCapacity; ix++) {
243  
      Object o = objects[ix];
244  
      if (o == null || o == deletedObject)
245  
        continue;
246  
      
247  
      int hash = o.hashCode();
248  
      int index = (hash & 0x7FFFFFFF) % newCapacity;
249  
      int offset = 1;
250  
251  
      // search for the object
252  
      while(newObjects[index] != null) { // no need to test for duplicates
253  
        index = ((index + offset) & 0x7FFFFFFF) % newCapacity;
254  
        offset = offset*2 + 1;
255  
256  
        if (offset == -1)
257  
          offset = 2;
258  
      }
259  
260  
      newObjects[index] = (A) o;
261  
    }
262  
263  
    objects = newObjects;
264  
    freecells = objects.length - elements;
265  
  }
266  
  
267  
  private class CompactHashIterator<T> implements Iterator<T> {
268  
    private int index;
269  
    private int lastReturned = -1;
270  
271  
    private int expectedModCount;
272  
273  
    @SuppressWarnings("empty-statement")
274  
    public CompactHashIterator() {
275  
      synchronized(CompactHashSet.this) {
276  
        for (index = 0; index < objects.length &&
277  
                        (objects[index] == null ||
278  
                        objects[index] == deletedObject); index++)
279  
          ;
280  
        expectedModCount = modCount;
281  
      }
282  
    }
283  
284  
    @Override
285  
    public boolean hasNext() {
286  
      synchronized(CompactHashSet.this) {
287  
        return index < objects.length;
288  
      }
289  
    }
290  
291  
    @SuppressWarnings("empty-statement")
292  
    @Override
293  
    public T next() {
294  
      synchronized(CompactHashSet.this) {
295  
        /*if (modCount != expectedModCount)
296  
          throw new ConcurrentModificationException();*/
297  
        int length = objects.length;
298  
        if (index >= length) {
299  
          lastReturned = -2;
300  
          throw new NoSuchElementException();
301  
        }
302  
  
303  
        lastReturned = index;
304  
        for (index += 1; index < length &&
305  
                         (objects[index] == null ||
306  
                          objects[index] == deletedObject); index++)
307  
          ;
308  
        if (objects[lastReturned] == nullObject)
309  
          return null;
310  
        else
311  
          return objects[lastReturned].get();
312  
      }
313  
    }
314  
315  
    @Override
316  
    public void remove() {
317  
      synchronized(CompactHashSet.this) {
318  
        if (modCount != expectedModCount)
319  
          throw new ConcurrentModificationException();
320  
        if (lastReturned == -1 || lastReturned == -2)
321  
          throw new IllegalStateException();
322  
        // delete object
323  
        if (objects[lastReturned] != null && objects[lastReturned] != deletedObject) {
324  
          objects[lastReturned] = (A) deletedObject;
325  
          elements--;
326  
          modCount++;
327  
          expectedModCount = modCount; // this is expected; we made the change
328  
        }
329  
      }
330  
    }
331  
  }
332  
}

Author comment

Began life as a copy of #1012355

download  show line numbers  debug dex  old transpilations   

Travelled to 13 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #1012720
Snippet name: WeakCompactHashSet (all in one object, abandoned attempt)
Eternal ID of this version: #1012720/4
Text MD5: 6ff647f52d328013b83695deec2858b1
Author: stefan
Category: javax / collections
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2021-07-11 15:55:09
Source code size: 9536 bytes / 332 lines
Pitched / IR pitched: No / No
Views / Downloads: 364 / 414
Version history: 3 change(s)
Referenced in: [show references]