@@ -12,6 +12,9 @@ package scala
12
12
package collection
13
13
package mutable
14
14
15
+ import java .lang .Integer .{numberOfLeadingZeros , rotateRight }
16
+ import scala .util .hashing .byteswap32
17
+
15
18
/** This class can be used to construct data structures that are based
16
19
* on hashtables. Class `HashTable[A]` implements a hashtable
17
20
* that maps keys of type `A` to values of the fully abstract
@@ -183,6 +186,7 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU
183
186
table(h) = e.next
184
187
tableSize = tableSize - 1
185
188
nnSizeMapRemove(h)
189
+ e.next = null
186
190
return e
187
191
} else {
188
192
var e1 = e.next
@@ -194,6 +198,7 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU
194
198
e.next = e1.next
195
199
tableSize = tableSize - 1
196
200
nnSizeMapRemove(h)
201
+ e1.next = null
197
202
return e1
198
203
}
199
204
}
@@ -227,8 +232,9 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU
227
232
var es = iterTable(idx)
228
233
229
234
while (es != null ) {
235
+ val next = es.next // Cache next in case f removes es.
230
236
f(es.asInstanceOf [Entry ])
231
- es = es. next
237
+ es = next
232
238
233
239
while (es == null && idx > 0 ) {
234
240
idx -= 1
@@ -357,15 +363,11 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU
357
363
358
364
protected def elemEquals (key1 : A , key2 : A ): Boolean = (key1 == key2)
359
365
360
- // Note:
361
- // we take the most significant bits of the hashcode, not the lower ones
362
- // this is of crucial importance when populating the table in parallel
363
- protected final def index (hcode : Int ) = {
364
- val ones = table.length - 1
365
- val improved = improve(hcode, seedvalue)
366
- val shifted = (improved >> (32 - java.lang.Integer .bitCount(ones))) & ones
367
- shifted
368
- }
366
+ /**
367
+ * Note: we take the most significant bits of the hashcode, not the lower ones
368
+ * this is of crucial importance when populating the table in parallel
369
+ */
370
+ protected final def index (hcode : Int ): Int = if (table.length == 1 ) 0 else improve(hcode, seedvalue) >>> numberOfLeadingZeros(table.length - 1 )
369
371
370
372
protected def initWithContents (c : HashTable .Contents [A , Entry ]) = {
371
373
if (c != null ) {
@@ -408,59 +410,20 @@ private[collection] object HashTable {
408
410
409
411
protected def elemHashCode (key : KeyType ) = key.##
410
412
411
- protected final def improve (hcode : Int , seed : Int ) = {
412
- /* Murmur hash
413
- * m = 0x5bd1e995
414
- * r = 24
415
- * note: h = seed = 0 in mmix
416
- * mmix(h,k) = k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; */
417
- // var k = hcode * 0x5bd1e995
418
- // k ^= k >> 24
419
- // k *= 0x5bd1e995
420
- // k
421
-
422
- /* Another fast multiplicative hash
423
- * by Phil Bagwell
424
- *
425
- * Comment:
426
- * Multiplication doesn't affect all the bits in the same way, so we want to
427
- * multiply twice, "once from each side".
428
- * It would be ideal to reverse all the bits after the first multiplication,
429
- * however, this is more costly. We therefore restrict ourselves only to
430
- * reversing the bytes before final multiplication. This yields a slightly
431
- * worse entropy in the lower 8 bits, but that can be improved by adding:
432
- *
433
- * `i ^= i >> 6`
434
- *
435
- * For performance reasons, we avoid this improvement.
436
- * */
437
- val i = scala.util.hashing.byteswap32(hcode)
438
-
439
- /* Jenkins hash
440
- * for range 0-10000, output has the msb set to zero */
441
- // var h = hcode + (hcode << 12)
442
- // h ^= (h >> 22)
443
- // h += (h << 4)
444
- // h ^= (h >> 9)
445
- // h += (h << 10)
446
- // h ^= (h >> 2)
447
- // h += (h << 7)
448
- // h ^= (h >> 12)
449
- // h
450
-
451
- /* OLD VERSION
452
- * quick, but bad for sequence 0-10000 - little entropy in higher bits
453
- * since 2003 */
454
- // var h: Int = hcode + ~(hcode << 9)
455
- // h = h ^ (h >>> 14)
456
- // h = h + (h << 4)
457
- // h ^ (h >>> 10)
458
-
459
- // the rest of the computation is due to SI-5293
460
- val rotation = seed % 32
461
- val rotated = (i >>> rotation) | (i << (32 - rotation))
462
- rotated
463
- }
413
+ /**
414
+ * Defer to a high-quality hash in [[scala.util.hashing ]].
415
+ * The goal is to distribute across bins as well as possible even if a hash code has low entropy at some bits.
416
+ * <p/>
417
+ * OLD VERSION - quick, but bad for sequence 0-10000 - little entropy in higher bits - since 2003
418
+ * {{{
419
+ * var h: Int = hcode + ~(hcode << 9)
420
+ * h = h ^ (h >>> 14)
421
+ * h = h + (h << 4)
422
+ * h ^ (h >>> 10)
423
+ * }}}
424
+ * the rest of the computation is due to SI-5293
425
+ */
426
+ protected final def improve (hcode : Int , seed : Int ): Int = rotateRight(byteswap32(hcode), seed)
464
427
}
465
428
466
429
/**
0 commit comments