HashingStrategy是您正在寻找的概念。它是一个策略接口,允许您定义 equals 和 hashcode 的自定义实现。
public interface HashingStrategy<E>
{
int computeHashCode(E object);
boolean equals(E object1, E object2);
}
您不能将 aHashingStrategy
与内置的HashSet
or一起使用HashMap
。GS Collections包括一个名为 java.util.SetUnifiedSetWithHashingStrategy
和一个名为 的 java.util.Map UnifiedMapWithHashingStrategy
。
让我们看一个例子。
public class Data
{
private final int id;
public Data(int id)
{
this.id = id;
}
public int getId()
{
return id;
}
// No equals or hashcode
}
这是您如何设置UnifiedSetWithHashingStrategy
和使用它的方法。
java.util.Set<Data> set =
new UnifiedSetWithHashingStrategy<>(HashingStrategies.fromFunction(Data::getId));
Assert.assertTrue(set.add(new Data(1)));
// contains returns true even without hashcode and equals
Assert.assertTrue(set.contains(new Data(1)));
// Second call to add() doesn't do anything and returns false
Assert.assertFalse(set.add(new Data(1)));
为什么不只使用 a Map
?UnifiedSetWithHashingStrategy
使用 a 的一半内存和 a 的UnifiedMap
四分之一内存HashMap
。有时您没有方便的键,必须创建一个合成键,例如元组。那会浪费更多的内存。
我们如何执行查找?请记住,集合有contains()
,但没有get()
。UnifiedSetWithHashingStrategy
除了实现Pool
之外Set
,它还实现了get()
.
这是处理不区分大小写字符串的简单方法。
UnifiedSetWithHashingStrategy<String> set =
new UnifiedSetWithHashingStrategy<>(HashingStrategies.fromFunction(String::toLowerCase));
set.add("ABC");
Assert.assertTrue(set.contains("ABC"));
Assert.assertTrue(set.contains("abc"));
Assert.assertFalse(set.contains("def"));
Assert.assertEquals("ABC", set.get("aBc"));
这展示了 API,但它不适合生产。问题是 HashingStrategy 不断委托给String.toLowerCase()
它创建一堆垃圾字符串。下面介绍如何为不区分大小写的字符串创建有效的散列策略。
public static final HashingStrategy<String> CASE_INSENSITIVE =
new HashingStrategy<String>()
{
@Override
public int computeHashCode(String string)
{
int hashCode = 0;
for (int i = 0; i < string.length(); i++)
{
hashCode = 31 * hashCode + Character.toLowerCase(string.charAt(i));
}
return hashCode;
}
@Override
public boolean equals(String string1, String string2)
{
return string1.equalsIgnoreCase(string2);
}
};
注意:我是 GS 收藏的开发人员。