gpt4 book ai didi

java - 如何在 java 中为作为其他属性列表的属性编写 equals 和 hashCode 方法

转载 作者:行者123 更新时间:2023-12-05 07:38:21 25 4
gpt4 key购买 nike

我有一个 HashMap,其中键是一个类,值是一个整数。我需要检查 map 中是否已存在该类的对象。我使用 containsKey(),但由于某些原因,当我在 equals()hashCode 中包含属性 sideDish 时它不起作用()。这是我的类(class)代码:

OrderItem 类:

@ToString
@Entity
@Table(name="OrderItem")
public class OrderItem implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Getter @Setter
private Long id;

@ManyToOne
@Getter @Setter
private Food food;

@ManyToMany
@Getter @Setter
private List<SideDish> sideDishes;

public OrderItem() {}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((food == null) ? 0 : food.hashCode());
result = prime * result + ((sideDishes == null) ? 0 : sideDishes.hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
OrderItem other = (OrderItem) obj;
if (food == null) {
if (other.food != null)
return false;
} else if (!food.equals(other.food))
return false;
if (sideDishes == null) {
if (other.sideDishes != null)
return false;
} else if (!sideDishes.equals(other.sideDishes))
return false;
return true;
}
}

食品类:

@ToString
@Entity
@Table(name="Food")
public class Food implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Getter @Setter
private Long id;

@Column(nullable = false, unique = true)
@NotNull(message = "Name cannot be null.")
@Getter @Setter
private String name;

@ManyToMany
@Getter @Setter
private List<SideDish> sidedishes;

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((foodtype == null) ? 0 : foodtype.hashCode());
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Food other = (Food) obj;
if (foodtype == null) {
if (other.foodtype != null)
return false;
} else if (!foodtype.equals(other.foodtype))
return false;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}

配菜类:

@Entity
@ToString(exclude= {"id","dishtype"})
@Table(name="SideDish")
public class SideDish implements Serializable, Comparable<SideDish>{

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Getter @Setter
private Long id;

@Getter @Setter
@Column(nullable = false, unique = true)
private String name;

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
SideDish other = (SideDish) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}

出于某种原因,如果我从 OrderItemequals()hashCode() 中删除 sideDish 属性> 类,它完美地工作。

但我还需要将 sideDish 作为对象标识的一部分进行检查。

下面是我的使用方法:

HashMap<OrderItem, Integer> orderItemsToSend = new HashMap<OrderItem, Integer>();

for (Order order : orders) {
for (OrderItem orderItem : order.getOrderItems()) {
int numSimilarOrders = getNumOfSimilarOrders(orderItem, orders);
if(!orderItemsToSend.containsKey(orderItem)) {
orderItemsToSend.put(orderItem, numSimilarOrders);
}else {
System.out.println("Vec je dodat item koji isti kao: " + orderItem.getFood().getName());
}
}
}

最佳答案

在你的OrderItem类,你的hashCode()equals()视乎属性(property)List<SideDish> sideDishes .

因此,如果sideDishes变化,hashCode() 也是如此(平等也是如此)。


A HashMap同时使用 hashCode()equals()存储和查找作为的对象。它使用一个名为“hash buckets”的概念。如果你把一个 key 放入 HashMap ,然后是 hashCode()更改,该对象将位于错误的哈希桶中,您将无法再次找到它。

key 是用于查找目的的东西 - 这就是“key”这个词的意思。无论是在数据库还是 HashMap 中,键的一个重要特性是不变性。所以在 Java 中,这意味着一个对象改变了它的 hashCode()。造成一把坏 key 。

这有点像文件系统通过文件名的哈希值进行查找,但随后您更改了文件名,但它并没有更新哈希值。您只能通过使用旧名称进行查找来找到该文件。


这个简单的测试程序将说明这一点。

我们在 HashMap 中存储了 2 个对象,然后更改 hashCode() .该 map 仍然包含这两个对象,但现在无法找到其中一个对象或无法将其用于查找。

解决方案是使用一些简单的不可变对象(immutable对象)作为,例如Long。其数据库 ID。

示例输出在代码下方。

public class HashTest {

static class Hashable {
String name;

@Override
public int hashCode() {
return ((name == null) ? 0 : name.hashCode());
}

@Override
public boolean equals(Object object) {
return (object instanceof Hashable) && equals((Hashable) object);
}

private boolean equals(Hashable that) {
return Objects.equals(this.name, that.name);
}

@Override
public String toString() {
// Use identityHashCode() so we can really see which object is which
return "[" + name + ":" + System.identityHashCode(this) + "]";
}
}

public static void main(String[] args) {
Hashable one = new Hashable();
one.name = "one";
Hashable two = new Hashable();
two.name = "one";

print(one, two);
two.name = "two";
print(one, two);

HashMap<Hashable, Integer> map = new HashMap<>();

map.put(one, 1);
map.put(two, 2);
find(map, one, two);

one.name = "two"; // Let's confuse things
print(one, two);
find(map, one, two);
}

private static void print(Hashable one, Hashable two) {
System.out.print("Names:" + one.name + ":" + two.name);
System.out.print("\tHashcodes:" + one.hashCode() + ":" + two.hashCode());
System.out.println("\tEquals:" + one.equals(two));
}

private static void find(HashMap<Hashable, Integer> map, Hashable one, Hashable two) {
System.out.print(map);
System.out.print("\tFound: " + map.get(one));
System.out.println("\tFound: " + map.get(two));
}
}

示例输出:

Names:one:one   Hashcodes:110182:110182 Equals:true
Names:one:two Hashcodes:110182:115276 Equals:false
{[one:366712642]=1, [two:1829164700]=2} Found: 1 Found: 2
Names:two:two Hashcodes:115276:115276 Equals:true
{[two:366712642]=1, [two:1829164700]=2} Found: 2 Found: 2

关于java - 如何在 java 中为作为其他属性列表的属性编写 equals 和 hashCode 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47978647/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com