mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-12-07 01:28:34 +08:00
fix(core):使用位运算解决极端情况下Math.abs()失败导致的BitSet报错
This commit is contained in:
parent
a31e3ff096
commit
6ad6a8022e
@ -50,12 +50,12 @@ public abstract class AbstractFilter implements BloomFilter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean contains(final String str) {
|
public boolean contains(final String str) {
|
||||||
return bitSet.get(Math.abs(hash(str)));
|
return bitSet.get(hash(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean add(final String str) {
|
public boolean add(final String str) {
|
||||||
final int hash = Math.abs(hash(str));
|
final int hash = hash(str);
|
||||||
if (bitSet.get(hash)) {
|
if (bitSet.get(hash)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -51,28 +51,40 @@ public class FuncFilter extends AbstractFilter {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param size 最大值
|
* @param size 最大值
|
||||||
* @param hashFunc Hash函数
|
* @param hashFuncs Hash函数
|
||||||
*/
|
*/
|
||||||
@SafeVarargs
|
@SafeVarargs
|
||||||
public FuncFilter(final int size, final Function<String, Number>... hashFunc) {
|
public FuncFilter(final int size, final Function<String, Number>... hashFuncs) {
|
||||||
super(size);
|
super(size);
|
||||||
Assert.notEmpty(hashFunc, "Hash functions must not be empty");
|
Assert.notEmpty(hashFuncs, "Hash functions must not be empty");
|
||||||
this.hashFuncs = Collections.unmodifiableList(Arrays.asList(hashFunc));
|
this.hashFuncs = Collections.unmodifiableList(Arrays.asList(hashFuncs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*兼容父类,如果存在多个哈希函数,就使用第一个
|
||||||
|
*
|
||||||
|
* @param str 字符串
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int hash(final String str) {
|
public int hash(final String str) {
|
||||||
return hash(str, hashFuncs.get(0));
|
return hash(str, hashFuncs.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param str 字符串
|
||||||
|
* @param hashFunc 哈希函数
|
||||||
|
* @return HashCode 指定哈希函数的计算结果
|
||||||
|
*/
|
||||||
public int hash(final String str, final Function<String, Number> hashFunc) {
|
public int hash(final String str, final Function<String, Number> hashFunc) {
|
||||||
return hashFunc.apply(str).intValue() % size;
|
// 通过位运算获取正数
|
||||||
|
return (hashFunc.apply(str).intValue() & 0x7FFFFFFF) % size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean contains(final String str) {
|
public boolean contains(final String str) {
|
||||||
for (final Function<String, Number> hashFunc : hashFuncs) {
|
for (final Function<String, Number> hashFunc : hashFuncs) {
|
||||||
if (!bitSet.get(Math.abs(hash(str, hashFunc)))) {
|
if (!bitSet.get(hash(str, hashFunc))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -83,7 +95,7 @@ public class FuncFilter extends AbstractFilter {
|
|||||||
public boolean add(final String str) {
|
public boolean add(final String str) {
|
||||||
boolean add = false;
|
boolean add = false;
|
||||||
for (final Function<String, Number> hashFunc : hashFuncs) {
|
for (final Function<String, Number> hashFunc : hashFuncs) {
|
||||||
int hash = Math.abs(hash(str, hashFunc));
|
int hash = hash(str, hashFunc);
|
||||||
if (!bitSet.get(hash)) {
|
if (!bitSet.get(hash)) {
|
||||||
bitSet.set(hash);
|
bitSet.set(hash);
|
||||||
add = true;
|
add = true;
|
||||||
|
|||||||
@ -20,6 +20,8 @@ import cn.hutool.v7.core.codec.hash.HashUtil;
|
|||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.BitSet;
|
||||||
|
|
||||||
public class BitMapBloomFilterTest {
|
public class BitMapBloomFilterTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -35,4 +37,5 @@ public class BitMapBloomFilterTest {
|
|||||||
Assertions.assertTrue(filter.contains("ddd"));
|
Assertions.assertTrue(filter.contains("ddd"));
|
||||||
Assertions.assertTrue(filter.contains("123"));
|
Assertions.assertTrue(filter.contains("123"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user