我想知道是否有人可以详细解释什么
(int)(l ^ (l >>> 32));
在下面的hashcode实现中(由eclipse生成,但与Effective Java相同):
private int i;
private char c;
private boolean b;
private short s;
private long l;
private double d;
private float f;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + i;
result = prime * result + s;
result = prime * result + (b ? 1231 : 1237);
result = prime * result + c;
long t = Double.doubleToLongBits(d);
result …Run Code Online (Sandbox Code Playgroud) 对象javadocs和Josh Bloch告诉我们如何实现hashCode/equals,好的IDE将正确处理各种类型的字段.所有的,有些讨论是在这里.
这个问题是关于下一步:你如何确保它们保持良好状态?
特别是,我觉得对于大多数类来说,equals/hashCode应该像Bloch建议的那样实现(以及Eclipse和其他IDE的实现),并考虑到该类中所有非派生的业务逻辑字段.在将新字段添加到类中作为继续工作的一部分时,人们常常忘记将它们添加到equals/hashCode实现中.当两个对象看起来相等时,这可能导致难以发现的错误,但实际上不同于最近引入的字段的值.
一个团队(甚至一个团队!)如何帮助确保类的equals/hashCode继续考虑所有相关字段,因为成员字段会发生变化?
我知道Apache的EqualsBuilder和HashCodeBuilder可以使用反射,这显然会考虑正确的字段,但我想避免使用它们的性能成本.是否有其他方法来标记未包含在equals/hashCode中的字段,应该是什么?静态代码分析,IDE功能,单元测试技术?
我们正在编写一个类,它需要非常复杂的逻辑来计算equals()和hashCode().与...有关的东西:
@Getters @Setters @FieldDefaults(level=AccessLevel.PRIVATE)
public class ExternalData {
TypeEnum type;
String data;
List<ExternalData> children;
}
Run Code Online (Sandbox Code Playgroud)
我们不构造这些对象,它们是从外部复杂系统的XML反序列化的.有20多种类型,根据类型数据可以忽略,或与子进行处理,或者没有子进程处理,每种类型节点的数据比较取决于类型.
我们创建了equals()和hashCode()以反映所有这些规则,但最近遇到了一个问题,即hashCode与equals不同步,导致将相等的对象添加到HashSet两次.我相信HashMap(以及HashSet就此而言)是用Java 实现的:https://en.wikipedia.org/wiki/Hash_table实现首先将对象放在基于hashCode的桶中,然后对每个桶进行检查等于.在不幸的情况下,2个相等的对象将进入不同的桶,它们将永远不会被equals()进行比较.通过"不同步"这里我的意思是他们进入不同的桶.
确保equals和hashCode不会失去同步的最佳方法是什么?
编辑:这个问题不同于在Java中覆盖equals和hashCode时应该考虑哪些问题? 他们在那里询问一般指导,并且接受的答案不适用于我的情况.他们说"make equals和hashCode一致",在这里我问我究竟是怎么做的.
我正在考虑使用Double作为HashMap的关键,但我知道浮点数比较是不安全的,这让我思考.Double类的equals方法也不安全吗?如果那样则意味着hashCode方法可能也是错误的.这意味着使用Double作为HashMap的关键将导致不可预测的行为.
任何人都可以在这里证实我的任何猜测吗?
我很清楚的合同需求,确保hashCode与一致equals,并且equals与一致compareTo.但是,这在实践中经常被违反.是否有可以自动测试此一致性的工具,技术或库?
我怀疑不幸的是答案是"不",但能够对这种可以利用库调用或框架的东西进行单元测试而不是需要手动编写自定义测试是有用的.每个重要的案例.
如果目前还不清楚我所说的一致意思是,hashCode和equals我指的是以下几点:
如果两个对象根据equals(Object)方法相等,则对两个对象中的每一个调用hashCode方法必须生成相同的整数结果.
对于equals和compareTo我指的是以下几点:
当且仅当e1.compareTo(e2)== 0具有与c的每个e1和e2的e1.equals(e2)相同的布尔值时,C类的自然排序被认为与equals一致.
我有两个表有一对一的关系,如下所示:
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
private int id;
private String name;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "book_dtail_id")
private BookDetail bookDetail;
}
@Entity
@Table(name = "book_detail")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BookDetail {
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
private Integer id;
@Column(name = "number_of_pages")
private Integer numberOfPages;
@OneToOne(mappedBy = "bookDetail")
private Book book;
}
Run Code Online (Sandbox Code Playgroud)
我使用表单输入数据如下
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BookForm {
Book book;
BookDetail bookDetail;
}
Run Code Online (Sandbox Code Playgroud)
控制器看起来像这样:
String handleNewBook(Model model){
Book book = …Run Code Online (Sandbox Code Playgroud) 根据我的理解ArrayList,默认容量为10,当它超过10时,它将创建一个具有新容量的新对象,依此类推.
因此,出于好奇,我输入下面的程序来检查hashcode()的ArrayList对象:
public class TestCoreJava {
public static void main(String [] args){
ArrayList al = new ArrayList();
for(int i=0;i<15;i++){
al.add("Temp"+i);
System.out.println("Hashcode for "+i+" element "+al.hashCode());
}
}
}
Run Code Online (Sandbox Code Playgroud)
根据上面的场景,当我没有设置ArrayList默认的初始容量时将是10.因此,在添加第11个元素时,它将创建一个新对象并增加容量ArrayList.
当我打印ArrayList对象的哈希码时,它hashcode()每次都会给出一个新的哈希码.
以下是o/p:
Hashcode for 0 element 80692955
Hashcode for 1 element -1712792766
Hashcode for 2 element -1476275268
Hashcode for 3 element 1560799875
Hashcode for 4 element 1220848797
Hashcode for 5 element -727700028
Hashcode for 6 element -1003171458 …Run Code Online (Sandbox Code Playgroud) 我似乎在标准的Java HashMap中获得了重复的键.通过"复制",我的意思是键的equals()方法相同.这是有问题的代码:
import java.util.Map;
import java.util.HashMap;
public class User {
private String userId;
public User(String userId) {
this.userId = userId;
}
public boolean equals(User other) {
return userId.equals(other.getUserId());
}
public int hashCode() {
return userId.hashCode();
}
public String toString() {
return userId;
}
public static void main(String[] args) {
User arvo1 = new User("Arvo-Part");
User arvo2 = new User("Arvo-Part");
Map<User,Integer> map = new HashMap<User,Integer>();
map.put(arvo1,1);
map.put(arvo2,2);
System.out.println("arvo1.equals(arvo2): " + arvo1.equals(arvo2));
System.out.println("map: " + map.toString());
System.out.println("arvo1 hash: " + …Run Code Online (Sandbox Code Playgroud) 正如标题所示,这是一个关于实现细节的问题HashMap#resize- 当内部数组的大小加倍时.这有点罗嗦,但我真的试图证明我对此有了最好的理解......
这发生在这个特定桶/箱中的条目以某种方式存储的时刻Linked- 因此具有确切的顺序并且在问题的上下文中这是重要的.
一般来说,resize也可以从其他地方调用,但我们只看这个案例.
假设你将这些字符串作为键放在一个HashMap(右边是hashcode 后面 HashMap#hash - 那是内部重新散列.)是的,这些都是精心生成的,而不是随机的.
DFHXR - 11111
YSXFJ - 01111
TUDDY - 11111
AXVUH - 01111
RUTWZ - 11111
DEDUC - 01111
WFCVW - 11111
ZETCU - 01111
GCVUR - 11111
Run Code Online (Sandbox Code Playgroud)
这里有一个简单的模式 - 最后4位对于所有这些都是相同的 - 这意味着当我们插入这些键中的8个(总共9个)时,它们最终会在同一个桶中; 并在9个HashMap#put时,resize将被调用.
因此,如果当前有8个条目(上面有一个键)HashMap- 这意味着在这个映射中有16个桶,它们的最后4个位决定了条目最终的位置.
我们把第九个键.此时TREEIFY_THRESHOLD被击中并被resize召唤.这些容器加倍,32并且键的另一位决定了该条目的位置(因此,现在为5位).
最终到达这段代码(当resize发生时):
Node<K,V> loHead = null, loTail = null;
Node<K,V> …Run Code Online (Sandbox Code Playgroud) 我在hashCode()为我创建的类编写方法时遇到了一些麻烦.此类旨在在TreeSet中使用,因此,它实现了Comparable.该类具有以下变量:
public class Node implements Comparable<Node> {
Matrix matrix;
int[] coordinates= new int[2];
Node father;
int depth;
int cost;
Run Code Online (Sandbox Code Playgroud)
这是该compareTo()方法的实现.我希望TreeSet按成本组织这些Node结构,因此,compareTo()返回简单减法的结果.
public int compareTo(Node nodeToCompare) {
return this.cost - nodeToCompare.cost;
}
Run Code Online (Sandbox Code Playgroud)
我还实现了一种equals()方法.
public boolean equals(Object objectToCompare) {
if(objectToCompare== this) {return true;}
if(objectToCompare== null || objectToCompare.getClass()!= this.getClass()) {return false;}
Node objectNode= (Node) objectToCompare;
return this.father.equals(objectNode.father) &&
this.depth== objectNode.depth &&
this.cost== objectNode.cost &&
this.matrix.equals(objectNode.matrix) &&
Arrays.equals(this.coordinates, objectNode.coordinates);
}
Run Code Online (Sandbox Code Playgroud)
说完这一切之后,我有几个问题:
equals()方法,我应该实现一个新hashCode() …