<?php
class Bloom {
// 哈希函数的数量
protected $hashNum = 3;
// 位数组的大小
protected $bitArrayCount = 1024*10;
// 位数组
protected $bitArray = [];
public function __construct()
{
// 构建默认的位数组,全部置为 false
$this->bitArray = array_pad([], $this->bitArrayCount, false);
}
/**
* 获取 hash 函数;也就是在位数组中,需要改为 true 的索引
* @param string $key 元素
* @return array
*/
protected function getIndexes($key)
{
$indexes = [];
for ($i = 0; $i < $this->hashNum; $i ++) {
$index = sprintf('%u', crc32($key . $i)); // 使用 crc32 散列
$index = $index % $this->bitArrayCount; // 获取 在位数组中的 位置
$indexes[] = $index;
}
return $indexes;
}
/**
* 向过滤器中添加元素
* @param string $key 要添加的元素
*/
public function addItem($key)
{
$indexes = $this->getIndexes($key);
// 将 hash 结果对应的位修改为 true
foreach ($indexes as $index) {
$this->bitArray[$index] = true;
}
}
/**
* 过滤器中是否存在这个元素; true 表示很可能存在,false 表示一定不存在
* @param string $key 元素
* @return array
*/
public function mightExist($key)
{
$indexes = $this->getIndexes($key);
foreach ($indexes as $index) {
if (! $this->bitArray[$index]) {
return false;
}
}
return true;
}
}
class Test
{
public function run()
{
$bloom = new Bloom();
// 向过滤器中添加 1000 个元素
for ($i = 0; $i < 100; $i ++) {
$bloom->addItem($i);
}
// 测试 过滤器判断结果
for ($i = 90; $i < 110; $i ++) {
$mightExist = $bloom->mightExist($i);
if ($mightExist) {
echo "might exist ", $i, PHP_EOL;
} else {
echo "not exist ", $i, PHP_EOL;
}
}
}
}
(new Test())->run();