我正在尝试在Scala中为Bloom过滤器建模。逻辑本身实际上非常简单明了,但是我正在努力找出如何充分利用Scala的数据结构来实现美观,惯用和实用的功能。
我的问题是:如果使用case类,则需要构造函数来生成哈希函数和将存储实际Bloom过滤器数据的bits数组。 但是,然后,在一种类似“添加”的方法中,它将更改bits数组的内容,我需要返回一个新的Bloom过滤器,而不是对现有过滤器的内容进行突变,以使我的方法具有参照透明性。
不幸的是,我无法构造一个新的Bloom过滤器,因为我不想让新的Bloom过滤器重新创建一个新的bits数组和新的hash函数,并且我也无法将其传递给现有的过滤器,因为bits数组和哈希函数都不是Bloom筛选器案例类的一部分。
那我应该如何在Scala中对此建模?
答案 0 :(得分:2)
[修改为使用BitSet
,后跟注释]
这是它可能如何工作的概述。
trait HashFunctions[T] {
def apply(value: T): BitSet
}
object Bloom {
class BloomFactory[T](hash: HashFunctions[T]) {
case class Bloom(flags: BitSet) {
def add(value: T): Bloom =
Bloom(flags union hash(value))
def test(value: T): Boolean =
hash(value).subsetOf(flags)
}
}
def apply[T](): BloomFactory[T]#Bloom = new BloomFactory(DefaultHashFunctions[T]).Bloom(BitSet.empty)
}
请注意,每次添加一个值时,这的确会创建一个新的Bloom
,但这会使类不可变,这是一个好主意。哈希函数是在伴随对象中创建的,因此每次您add
进入过滤器时都不会发生。
显然,这可以使速度和内存使用效率大大提高。