我相信我通过识别哪些字段应该是散列/相等测试的一部分来阅读在编译期间(使用APT)生成equals/hashcode/toString方法的人.我在网上找不到那样的东西(我可能梦见过它?)......
这可以这样做:
public class Person {
@Id @GeneratedValue private Integer id;
@Identity private String firstName, lastName;
@Identity private Date dateOfBirth;
//...
}
Run Code Online (Sandbox Code Playgroud)
对于一个实体(所以我们想要排除一些字段,比如id).
或者像scala案例类,即值对象:
@ValueObject
public class Color {
private int red, green, blue;
}
Run Code Online (Sandbox Code Playgroud)
不仅文件变得更易读和更容易编写,而且它还有助于确保所有属性都是equals/hashcode的一部分(如果您稍后添加其他属性,而不相应地更新方法).
我听说APT在IDE中得不到很好的支持,但我不认为这是一个主要问题.毕竟,测试主要由持续集成服务器运行.
有没有想过这是否已经完成,如果不是为什么?谢谢
我有两个字符串,id喜欢使用它们作为字典键,但我有点懒惰创建另一个对象,计算字符串的哈希码等.
所以不是那样,我可以获得两个字符串的哈希码,添加它们并使用结果作为字典的键吗?
有可能引起碰撞吗?对?.
有任何想法吗?
我有道德困境.我的应用程序中有一些值对象,它们是不可变的,非常简单.我用IDE生成了equals和hashcode(在我的例子中是intellij),但这样做,使代码覆盖率下降,加上报告现在表明那些值对象非常复杂(使用圈复杂度量度量)实际上他们很简单.
例如,以下等于在具有3个不可变属性的值对象中.代码复杂度为14(javaNCSS),它有26个执行分支(Cobertura).我还应该补充一点,如果任何方法的复杂度大于10,我就会失败.
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
TranscriptTaskDetails that = (TranscriptTaskDetails) o;
if (inputFile != null ? !inputFile.equals(that.inputFile) : that.inputFile != null) {
return false;
}
if (language != that.language) {
return false;
}
if (outputFile != null ? !outputFile.equals(that.outputFile) : that.outputFile != null) {
return false;
}
return true;
}
Run Code Online (Sandbox Code Playgroud)
我想知道其他开发人员使用什么来规避这一点,因为我非常关注复杂性报告,因为根据我的经验,高复杂度指标涉及更多错误,所以这个自动生成的equals和hashcode正在污染报告.
我正在考虑使用来自apache commons-lang的EqualsBuilder和HashcodeBuilder来规避这个问题,但我并不百分之百:S.
我应该补充一点,我为这个项目编写的代码部分是一个将被其他业务部门使用的库......并且将由不同的团队维护:S.
我已经定义了一个子接口,java.util.Collection它实际上是一个multiset(又名包).它可能不包含null元素,尽管这对我的问题并不重要.接口定义的equals合同正如您所期望的那样:
obj instanceof MyInterfaceobj包含与this(by equals)相同的元素obj 每个元素包含相同数量的重复项现在我想写我的hashCode方法.我最初的想法是:
int hashCode = 1;
for( Object o : this ) {
hashCode += o.hashCode();
}
Run Code Online (Sandbox Code Playgroud)
但是,我注意到com.google.common.collect.Multiset(来自Guava)定义了哈希码,如下所示:
int hashCode = 0;
for( Object o : elementSet() ) {
hashCode += ((o == null) ? 0 : o.hashCode()) ^ count(o);
}
Run Code Online (Sandbox Code Playgroud)
令我感到奇怪的是,一个空的Multiset会有哈希码0,但更重要的是,我不理解^ count(o)简单地添加每个副本的哈希码的好处.也许这不是一次多次计算相同的哈希码,但为什么不* count(o)呢?
我的问题:什么是有效的哈希码计算?在我的情况下,元素的计数不能保证很便宜.
如果我实现equals()和hashCode()两个父类和子类,是有必要呼吁super.equals()在equals()在子类中,如
public boolean equals(Object obj) {
if (obj.getClass() != ChildClass.class) {
return false;
}
return super.equals() && this.var == ((ChildClass) obj).var;
}
Run Code Online (Sandbox Code Playgroud)
我假设父类不是Object,并且给出了equals和hashCode的正确定义.
如果需要使用a Class<T>作为键的一部分Map来定义hashCode和的正确方法是什么equals?
A Class<T>继承Object检查引用相等性并将内存地址作为哈希码返回的那些,但在我看来,不清楚a的有意义的定义equals和hashCode定义是什么Class<T>.
我应该使用theClass.getClass().hashCode();例如(我们有Class<T> theClass;)使用实际实例的方法吗?
但这似乎不是正确的做法.
例如在javadoc中Class<T>:
每个数组也属于一个类,它反映为一个Class对象,由具有相同元素类型和维数的所有数组共享
所以在某些情况下似乎在Class<T>对象之间共享?那么接下来的方法是什么?也许使用theClass.hashCode()和theClass.equals()使用引用相等?这里根本不确定.
我想知道为什么Hashtable避免使用负哈希码?
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
Run Code Online (Sandbox Code Playgroud)
哪里(hash & 0x7FFFFFFF)使有符号位为0为正,但为什么我们不能将带符号的32位整数视为无符号?甚至使用模块化技巧使其变得积极.例如,
public static long int_mod(int hashcode, int tab_length){
return (hashcode % tab_length + tab_length) % tab_length;
}
Run Code Online (Sandbox Code Playgroud) 我想为字符串生成一个整数哈希码,它将永远保持不变; 即相同的字符串应始终产生相同的哈希码.
散列不必是加密安全的,它不会用于密码或敏感数据.
我的第一次尝试是使用.net框架string.GetHashCode()函数.但是在阅读消息来源后,我发现了以下内容:
Run Code Online (Sandbox Code Playgroud)// We want to ensure we can change our hash function daily. // This is perfectly fine as long as you don't persist the // value from GetHashCode to disk or count on String A // hashing before string B. Those are bugs in your code. hash1 ^= ThisAssembly.DailyBuildNumber;
这似乎表明哈希码不会保持不变.
如果是这样,框架是否有另一种方法来生成可重复的哈希码?或者GetHashCode的代码是否是实现我自己的代码的合理起点?
我正在寻找尽可能轻巧和快速的东西.
我找到了System.Security.Cryptography.MD5,但对于一个简单的int32哈希码来说这似乎有点过头了,我担心开销.至少它需要从字符串转换为字节数组,从字节数组转换为int,并MD5()为每个散列创建新对象,或管理某些静态共享MD5对象().
我在看HashMapJDK8 的实现.在get方法中,我看到下面的行,用于查找与给定键匹配的Node.
if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k))))
Run Code Online (Sandbox Code Playgroud)
为什么需要将哈希值与密钥进行比较?为什么上面的行不写为:
if (((k = e.key) == key) || (key != null && key.equals(k)))
Run Code Online (Sandbox Code Playgroud)
为什么这样做是否有任何解释?谢谢.
在查看覆盖的不同选项时hashCode(),我被引导到Objects.hashCode(Object[])Google的guava-libraries(javadoc)中.javadoc表示它委托给Arrays.hashCode(Object[]).在许多不同的对象类型中使用此方法是否安全?这不容易发生哈希冲突,或者这不仅仅是因为容器通常只包含一种类型的对象?
举个简单的例子,考虑以下类,
public class Student {
private final String name;
public Student(String name) {
this.name = name;
}
@Override
public int hashCode() {
return Objects.hashCode(name);
}
}
public class Teacher {
private final String name;
public Teacher(String name) {
this.name = name;
}
@Override
public int hashCode() {
return Objects.hashCode(name);
}
}
public class HashCodeDriver {
public static void main(String[] args) {
final String name = "moe";
Student s = new Student(name); …Run Code Online (Sandbox Code Playgroud) hashcode ×10
java ×8
equals ×4
hash ×3
c# ×2
guava ×2
hashmap ×2
string ×2
annotations ×1
apt ×1
comparison ×1
dictionary ×1
gethashcode ×1
hashtable ×1
multiset ×1
unit-testing ×1