Java 插入密钥时自定义等于/哈希(番石榴缓存)
简单地说,我必须重写缓存选择正确键的方式,因为在检索键时不应考虑某些字段(例如,时间戳、消息id等)。 我无法修改key对象的实际哈希函数,因为它已用于在代码中识别Java 插入密钥时自定义等于/哈希(番石榴缓存),java,hash,equals,guava,Java,Hash,Equals,Guava,简单地说,我必须重写缓存选择正确键的方式,因为在检索键时不应考虑某些字段(例如,时间戳、消息id等)。 我无法修改key对象的实际哈希函数,因为它已用于在代码中识别 有番石榴贮藏库吗?还有解决办法? 这是我的配置: CacheBuilder.newBuilder().maximumSize(CACHE_SIZE).recordStats(). expireAfterWrite(DEFAULT_AGE, TimeUnit.DAYS).build( new CacheLoader&
有番石榴贮藏库吗?还有解决办法?
这是我的配置:
CacheBuilder.newBuilder().maximumSize(CACHE_SIZE).recordStats().
expireAfterWrite(DEFAULT_AGE, TimeUnit.DAYS).build(
new CacheLoader<Request, Response>() {
@Override
public Response load(Request request) {
return request.getResponse();
}
});
您可以简单地将
请求
对象包装到缓存请求
对象中,其中缓存请求
将基于所需字段实现hashCode()
和equals()
,如果无法修改哈希函数,则提供对包装的请求
的访问权(我仍然不明白为什么),那么您需要为缓存使用“包装器”密钥,例如:
public class RequestKey {
private final Request _req;
public int hashCode() {
// use appropriate Request fields here
}
public boolean equals(Object o) {
return ((this == o) || ((o != null) && (getClass() == o.getClass()) && _req.equals(((RequestKey)o)._req)));
}
}
我很确定,使用番石榴是不可能的。有一些使用自定义等价物的合法案例,但他们说它们太少,无法由
CacheBuilder
和MapMaker
处理。1甚至有com.google.common.base.Equivalence
,但它只在内部使用(另请参见和)
您需要在要用于查找的字段中设置自己的密钥,或者将请求
包装到另一个对象中,以您想要的方式定义equals
和hashCode
1当使用与默认的
equals
/hashCode
不同的东西时,唯一的情况是使用weakKeys
(软键
),然后是==
/系统。identityHashCode
组合。在任何情况下,您都不能自由选择等效项。如果使用Lombok:
有一个Lombok注释@EqualsAndHashCode
,它覆盖hashCode
和equals
,以对象的非静态、非瞬态属性为基础。因此,对于以下内容,如果您比较两个使用相同的姓名
、年龄
和工资
创建的员工,他们的评估结果将为@EqualsAndHashCode
public class Employee {
private String name;
private int age;
private int salary;
}
如果您有不希望包含的属性,可以使用@EqualsAndHashCode.Exclude
标记它们
@EqualsAndHashCode
public class Employee {
private String name;
@EqualsAndHashCode.Exclude
private int age;
@EqualsAndHashCode.Exclude
private int salary;
}
您还可以特别包括具有以下内容的字段:
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class Employee {
@EqualsAndHashCode.Include
private String name;
@EqualsAndHashCode.Include
private int age;
private int salary;
}
Lombok注释文档:
示例来自:如果它使用自己的哈希实现,我无法想象它会是一个非常有用的实用程序。另外,您能否进一步解释“我不能修改我的哈希()函数,因为它已经用于识别“真实”等于对象”的意思?事实上,我并不是要求添加此功能,但如果有人知道如何处理此情况,您可以通过在密钥(即您的请求)上适当地实现hashCode()和equals()来处理此情况。仅从
hashCode
中删除字段,而将其保留在equals
中。1.可能对性能有害,2.肯定正确,3.毫无意义。虽然@Hamal000没有提到他的equals,但我认为其中也包含了字段。我无法修改哈希,因为它是遗留代码,并且哈希已在某个位置使用还有。@Hamal000-我理解。但是,从hashcode中删除字段不应该降低它在其他地方的有用性(除非您一直将这些hashcode存储在例如数据库中)嗯,删除一个字段意味着缩小散列函数映射对象的空间,但这不是问题所在……不幸的是,在我的例子中,散列被用作客户端某处的id(使用此函数)。等价性是公共的:@fry:的确是,但只有一个公共用途(在Maps.difference
中)。
@EqualsAndHashCode
public class Employee {
private String name;
@EqualsAndHashCode.Exclude
private int age;
@EqualsAndHashCode.Exclude
private int salary;
}
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class Employee {
@EqualsAndHashCode.Include
private String name;
@EqualsAndHashCode.Include
private int age;
private int salary;
}