如何在Scala中建模bloom过滤器
我正在尝试在Scala中模拟bloom过滤器。逻辑本身实际上非常简单,但我正在努力弄清楚如何充分使用Scala的数据结构,使其具有良好的、惯用的和功能性的特性 我的问题是:如果我使用case类,我需要构造函数来生成散列函数和将存储实际bloom过滤器数据的位数组。 但是,在像“add”这样会更改位数组内容的方法中,我需要返回一个新的bloom过滤器,而不是改变现有过滤器的内容,以使我的方法具有引用透明性 不幸的是,我不能构造一个新的bloom筛选器,因为我不希望新的筛选器重新创建一个新的位数组和新的哈希函数,而且我也不能将其传递给现有的筛选器,因为位数组和哈希函数都不是bloom筛选器case类的一部分如何在Scala中建模bloom过滤器,scala,data-structures,functional-programming,case-class,bloom-filter,Scala,Data Structures,Functional Programming,Case Class,Bloom Filter,我正在尝试在Scala中模拟bloom过滤器。逻辑本身实际上非常简单,但我正在努力弄清楚如何充分使用Scala的数据结构,使其具有良好的、惯用的和功能性的特性 我的问题是:如果我使用case类,我需要构造函数来生成散列函数和将存储实际bloom过滤器数据的位数组。 但是,在像“add”这样会更改位数组内容的方法中,我需要返回一个新的bloom过滤器,而不是改变现有过滤器的内容,以使我的方法具有引用透明性 不幸的是,我不能构造一个新的bloom筛选器,因为我不希望新的筛选器重新创建一个新的位数组和
那么,我应该如何在Scala中对此进行建模呢?[修改为使用
位集,注释如下]
这是它可能如何工作的概述
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
,但这会使类不可变,这是一个好主意。散列函数是在伴随对象中创建的,因此每次将添加到过滤器时都不会发生这种情况
显然,这在速度和内存使用方面都可以显著提高效率。[修改为使用位集,注释如下]
这是它可能如何工作的概述
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
,并将哈希函数private
保留在伴随对象中。(但这只是我的想法。)我认为您应该将位数组私有
保留到实例中,使用每个add
创建一个新的,并将哈希函数private
保留到伴随对象中。(但这只是我的想法。)也许不是用Set[Int]
?我用了一个Array[Boolean]
,而是用我的hash函数@AlexanderAzarov给出的索引切换布尔值。但我看过其他的实现,它们确实在使用位集。使用位集(或Set[Int])有什么好处?@AlexanderAzarov谢谢,我已经修改为使用位集
,这对于添加和更新都可能更快。也许我使用了数组[Boolean]
,而不是集[Int]
,这是一种天真的方法,我在我的hash函数@AlexanderAzarov给出的索引处切换布尔值。但我看过其他的实现,它们确实在使用位集。使用位集(或Set[Int])有什么好处?@AlexanderAzarov谢谢,我已经修改为使用BitSet
,这对于添加和更新都可能更快。