7
\$\begingroup\$

Due to a performance profiling hotspot detailed here, I implemented my own BitSet using Java's BitSet. This is intended to replace the Enumeration.ValueSet. However, it's a bit awkward to use, primarily due to my likely misunderstanding of the relationships between the Enumeration class, Enumeration type and concrete Enumeration object.

In my enumeration objects, I have to have code like this:

type BitSet = alder.BitSet[this.type]
val empty = alder.BitSet[this.type]()

Elsewhere, I need to do things like this:

alder.BitSet.fromBitMask[SomeEnumeration.type](...)

For mkString I need to actually pass in the enumeration object itself. Is there any way to make this entire edifice a little more user-friendly?

package alder
import scala.language.implicitConversions
class BitSet[E <: Enumeration](val bits: java.util.BitSet) {
 def isEmpty: Boolean = bits.isEmpty
 def nonEmpty: Boolean = !isEmpty
 override def hashCode = bits.hashCode
 override def equals(o: Any) = o match {
 case that: BitSet[E] => this.bits equals that.bits
 case _ => false
 }
 def union(that: BitSet[E]): BitSet[E] = {
 var newBits = bits
 newBits.or(that.bits)
 new BitSet[E](newBits)
 }
 def |(that: BitSet[E]): BitSet[E] = union(that)
 def |(v: E#Value): BitSet[E] = union(BitSet(v))
 def intersection(that: BitSet[E]): BitSet[E] = {
 var newBits = bits
 newBits.and(that.bits)
 new BitSet(newBits)
 }
 def &(that: BitSet[E]): BitSet[E] = intersection(that)
 def &(v: E#Value): BitSet[E] = intersection(BitSet(v))
 def contains(v: E#Value): Boolean = bits.get(v.id)
 def containsAll(that: BitSet[E]): Boolean = intersection(that) == that
 def containsAny(that: BitSet[E]): Boolean = intersection(that).nonEmpty
 def toBitMask(): Array[Long] = bits.toLongArray
 def mkString(e: E, sep: String): String =
 {
 val vs = e.ValueSet.fromBitMask(toBitMask())
 vs.mkString(sep)
 }
}
object BitSet {
 def apply[E <: Enumeration](): BitSet[E] = new BitSet[E](new java.util.BitSet)
 def apply[E <: Enumeration](vs: E#Value*): BitSet[E] = {
 var bits = new java.util.BitSet
 for (v <- vs) {
 bits.set(v.id)
 }
 new BitSet[E](bits)
 }
 def fromBitMask[E <: Enumeration](mask: Array[Long]): BitSet[E] =
 new BitSet[E](java.util.BitSet.valueOf(mask))
}
asked Dec 24, 2014 at 19:05
\$\endgroup\$
1

2 Answers 2

8
\$\begingroup\$

After studying your code for a good long while, I realized that the reason you haven't gotten an answer is that there isn't really much to say about your code. Well done!

I would recommend adding some thorough ScalaDoc though. It has been my experience that Scala library developers have far too much faith in the ability of library users to magically understand what they really meant. Examples are wonderful things.

answered Jul 2, 2015 at 16:17
\$\endgroup\$
1
  • \$\begingroup\$ Thanks, it all still seems pretty awkward to me though... \$\endgroup\$ Commented Jul 2, 2015 at 18:36
2
\$\begingroup\$

In union(), you wrote new Bitset[E](newBits), but in intersection(), you wrote new BitSet(newBits). Even if they work the same, consistency would be good.

You have functions like union and redundant symbolic operators like |. I suggest that a.union(b) should mutate a, whereas a | b should return a new BitSet.

There are a few more operations that would be necessary for a useful bitset, such as not (a.k.a flip) and xor. It would also be nice to be able to test whether a particular bit is set without having to call toBitMask(). Compare your wrapper against java.util.BitSet to see what is missing.

answered Jul 9, 2015 at 19:02
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.