golang兼容Java Guava的高效布隆过滤器实现插件库bloomfilter的使用
Golang兼容Java Guava的高效布隆过滤器实现插件库bloomfilter的使用
概述
这是Go语言中另一个布隆过滤器的实现,与Java的Guava库兼容。该库借鉴了Java Guava库实现布隆过滤器哈希策略的方式,以实现序列化兼容性。
安装
首先获取最新版本的库:
go get github.com/OldPanda/bloomfilter
然后在代码中导入这个库:
import "github.com/OldPanda/bloomfilter"
使用示例
基本用法
package main
import (
"fmt"
"github.com/OldPanda/bloomfilter"
)
func main() {
// 创建布隆过滤器,预期插入500个元素,错误率0.01
bf, _ := bloomfilter.NewBloomFilter(500, 0.01)
// 将数字0~199添加到布隆过滤器中
for i := 0; i < 200; i++ {
bf.Put(i)
}
// 检查数字100和200是否在布隆过滤器中
fmt.Println(bf.MightContain(100))
fmt.Println(bf.MightContain(200))
}
序列化
package main
import "github.com/OldPanda/bloomfilter"
func main() {
// 预期插入500个元素,错误率0.01
bf, _ := bloomfilter.NewBloomFilter(500, 0.01)
// 将0~199添加到布隆过滤器中
for i := 0; i < 200; i++ {
bf.Put(i)
}
// 将布隆过滤器序列化为字节数组
bytes := bf.ToBytes()
// 处理字节数组...
}
反序列化
package main
import (
"fmt"
"github.com/OldPanda/bloomfilter"
)
func main() {
// 从字节数组创建布隆过滤器
bf, _ := bloomfilter.FromBytes(bytes)
// 检查数字100是否在布隆过滤器中
fmt.Println(bf.MightContain(100))
}
性能测试
性能测试分别运行元素插入和查询操作。
» go test -bench . -benchmem ./...
# github.com/OldPanda/bloomfilter.test
goos: darwin
goarch: arm64
pkg: github.com/OldPanda/bloomfilter
BenchmarkBloomfilterInsertion-12 11091939 90.62 ns/op 17 B/op 1 allocs/op
BenchmarkBloomfilterQuery-12 20389624 53.16 ns/op 15 B/op 1 allocs/op
BenchmarkBloomfilterDeserialization-12 293098 3767 ns/op 13200 B/op 52 allocs/op
PASS
ok github.com/OldPanda/bloomfilter 3.719s
更多关于golang兼容Java Guava的高效布隆过滤器实现插件库bloomfilter的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang兼容Java Guava的高效布隆过滤器实现插件库bloomfilter的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang中兼容Java Guava的高效布隆过滤器实现
布隆过滤器(Bloom Filter)是一种空间效率极高的概率型数据结构,用于判断一个元素是否在一个集合中。在Golang中,虽然没有官方兼容Java Guava的实现,但有多个高质量的布隆过滤器库可以实现类似功能。
推荐库
- github.com/bits-and-blooms/bloom - 最流行的Golang布隆过滤器实现
- github.com/willf/bloom - 另一个广泛使用的实现
基本使用示例
安装
go get github.com/bits-and-blooms/bloom
基本用法
package main
import (
"fmt"
"github.com/bits-and-blooms/bloom"
)
func main() {
// 创建一个预期容量为10000,误判率为0.01%的布隆过滤器
filter := bloom.NewWithEstimates(10000, 0.0001)
// 添加元素
filter.Add([]byte("hello"))
filter.Add([]byte("world"))
// 测试元素是否存在
fmt.Println(filter.Test([]byte("hello"))) // true
fmt.Println(filter.Test([]byte("world"))) // true
fmt.Println(filter.Test([]byte("golang"))) // false
// 批量添加
elements := [][]byte{[]byte("apple"), []byte("banana"), []byte("orange")}
for _, e := range elements {
filter.Add(e)
}
// 测试批量元素
fmt.Println(filter.Test([]byte("apple"))) // true
fmt.Println(filter.Test([]byte("pear"))) // false
}
与Java Guava兼容的特性实现
虽然Golang中没有直接兼容Guava的库,但我们可以模拟Guava的一些关键特性:
1. 可配置的误判率
func createFilter(expectedElements uint, falsePositiveRate float64) *bloom.BloomFilter {
m, k := bloom.EstimateParameters(expectedElements, falsePositiveRate)
return bloom.New(m, k)
}
2. 合并多个布隆过滤器
func mergeFilters(filters ...*bloom.BloomFilter) (*bloom.BloomFilter, error) {
if len(filters) == 0 {
return nil, fmt.Errorf("no filters to merge")
}
base := filters[0]
for _, f := range filters[1:] {
if base.Cap() != f.Cap() || base.K() != f.K() {
return nil, fmt.Errorf("incompatible filters")
}
base.Union(f)
}
return base, nil
}
3. 序列化和反序列化
func saveFilter(filter *bloom.BloomFilter, filename string) error {
data, err := filter.GobEncode()
if err != nil {
return err
}
return os.WriteFile(filename, data, 0644)
}
func loadFilter(filename string) (*bloom.BloomFilter, error) {
data, err := os.ReadFile(filename)
if err != nil {
return nil, err
}
filter := &bloom.BloomFilter{}
if err := filter.GobDecode(data); err != nil {
return nil, err
}
return filter, nil
}
性能优化技巧
-
选择合适的参数:
- 更大的容量会减少误判率但增加内存使用
- 更多的哈希函数会减少误判率但增加计算时间
-
批量操作:
// 批量添加比单个添加更高效 func batchAdd(filter *bloom.BloomFilter, items [][]byte) { for _, item := range items { filter.Add(item) } }
-
使用sync.Pool重用过滤器:
var filterPool = sync.Pool{ New: func() interface{} { return bloom.NewWithEstimates(100000, 0.01) }, } func getFilter() *bloom.BloomFilter { return filterPool.Get().(*bloom.BloomFilter) } func putFilter(filter *bloom.BloomFilter) { filter.ClearAll() filterPool.Put(filter) }
与Java Guava的主要区别
-
API设计:
- Guava使用泛型,Golang使用[]byte作为输入
- Guava有更丰富的构建器模式配置
-
序列化格式:
- 不兼容,需要自定义转换如果需要与Java系统交互
-
哈希策略:
- 实现细节不同,但效果相似
结论
虽然Golang中没有直接兼容Java Guava的布隆过滤器实现,但bits-and-blooms/bloom
库提供了类似的功能和性能。通过适当的封装,可以在Golang中实现与Guava相似的使用体验。对于需要与Java系统交互的场景,可以考虑在边界处进行序列化格式的转换。