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 | } |
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: | 418 / 487 |
Version history: | 3 change(s) |
Referenced in: | [show references] |