diff options
author | Rex Kerr <ichoran@gmail.com> | 2013-11-10 15:05:58 -0800 |
---|---|---|
committer | Rex Kerr <ichoran@gmail.com> | 2013-11-18 01:41:30 -0800 |
commit | 05aedd936e7e7bcf0fa2443abd58b39732f173a9 (patch) | |
tree | 96afe8ba6a01411d6a740743d53dcd61939958e6 /test | |
parent | d2cee3a5e1d26ba27fd7912d48b1e7af0beb844a (diff) | |
download | scala-05aedd936e7e7bcf0fa2443abd58b39732f173a9.tar.gz scala-05aedd936e7e7bcf0fa2443abd58b39732f173a9.tar.bz2 scala-05aedd936e7e7bcf0fa2443abd58b39732f173a9.zip |
New mutable hash map with Long keys: partially solves SI-5263 and is relevant
to SI-6825.
The hash map is based on an open addressing scheme that provides
dramatically faster (mostly due to specialization) get and contains
operations than either the standard Java HashMap or any of the existing
Scala hash maps. It doesn't work well above 500,000,000 elements as
the arrays cannot scale past 2^30 elements. Maps are not faster in
general due to the lack of specialization of Function1[Long, V].
Revisions made sure that all return types in the public API are specified.
Also switched to a leading-zeros method of calculating the initial mask (to
save a few ns), and used an occasionally-more-efficient version of
seekEntryOrOpen. Also edited out specific performance numbers and moved
constants to companion.
Diffstat (limited to 'test')
-rw-r--r-- | test/files/run/mutable-longmap.scala | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/test/files/run/mutable-longmap.scala b/test/files/run/mutable-longmap.scala new file mode 100644 index 0000000000..07fd80f6f0 --- /dev/null +++ b/test/files/run/mutable-longmap.scala @@ -0,0 +1,79 @@ +object Test extends App { + + import scala.collection.mutable.HashMap; + import scala.collection.mutable.LongMap; + + val keys = Array( + Long.MinValue, Int.MinValue - 1L, Int.MinValue, -9127, -1, + 0, 1, 9127, Int.MaxValue, Long.MaxValue + ) + + val rn = new scala.util.Random(42L) + var lm = LongMap.empty[Long] + val hm = HashMap.empty[Long,Long] + + def checkConsistent = hm.forall{ case (k,v) => lm.get(k).exists(_ == v) } + + assert { + (0 to 10000).forall{ i => + val k = keys(rn.nextInt(keys.length)) + if (rn.nextInt(100) < 2) lm = lm.clone() + if (rn.nextInt(100) < 5) lm.repack() + if (rn.nextBoolean) { + hm += ((k, i)) + rn.nextInt(6) match { + case 0 => lm += ((k, i)) + case 1 => lm += (k, i) + case 2 => lm(k) = i + case 3 => lm.put(k,i) + case 4 => lm ++= List((k,i)) + case _ => if (!lm.contains(k)) lm.getOrElseUpdate(k,i) + else lm += (k,i) + } + } + else { + hm -= k + rn.nextInt(2) match { + case 0 => lm -= k + case _ => lm --= List(k) + } + } + checkConsistent + } + } + + assert { + lm.map{ case (k,v) => -k*k -> v.toString }.getClass == lm.getClass + } + + assert { + val lm2 = new LongMap[Unit](2000000) + for (i <- 0 until 1000000) lm2(i) = () + + lm2.size == 1000000 && + (0 to 1100000 by 100000).forall(i => (lm2 contains i) == i < 1000000) + } + + lm = LongMap(8L -> 22L, -5L -> 5L, Long.MinValue -> 0L) + + assert{ var s = 0L; lm.foreachKey(s += _); s == Long.MinValue + 3 } + assert{ var s = 0L; lm.foreachValue(s += _); s == 27L } + assert { + val m2 = lm.mapValuesNow(_+2) + lm.transformValues(_+2) + m2 == lm && !(m2 eq lm) && (for ((_,v) <- lm) yield v).sum == 33L + } + + assert { + val lm2 = new LongMap[String](_.toString) + lm2 += (5L -> "fish", 0L -> "unicorn") + val hm2 = (new HashMap[Long,String]) ++= lm2 + + List(Long.MinValue, 0L, 1L, 5L).forall(i => + lm2.get(i) == hm2.get(i) && + lm2.getOrElse(i, "") == hm2.getOrElse(i, "") && + lm2(i) == hm2.get(i).getOrElse(i.toString) && + lm2.getOrNull(i) == hm2.get(i).orNull + ) + } +} |