gpt4 book ai didi

java - 如何覆盖 HashSet 的 equals()、hashcode() 和 compareTo()

转载 作者:搜寻专家 更新时间:2023-11-01 03:17:24 24 4
gpt4 key购买 nike

我正在尝试为我的 HashSet 覆盖提到的方法:

Set<MyObject> myObjectSet = new HashSet<MyObject>();

我的对象:

public class MyObject implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
String name;
int number;
Map<String,String> myMap;

public MyObject(String name, int number, Map<String,String> myMap) {
this.name = name;
this.number = number;
this.myMap = myMap;
}

[...]
}

如何覆盖 hashcode()、equals() 和 compareTo() 方法?


目前我有以下内容:

public int hashCode () {
return id.hashCode();
}

// override the equals method.
public boolean equals(MyObject s) {
return id.equals(s.id);
}

// override compareTo
public int compareTo(MyObject s) {
return id.compareTo(s.id);
}

我读到通过 id 进行比较是不够的,这是对象是数据库的持久实体(请参阅 here)。

此类型的所有对象的名称和编号并非唯一。

那么我应该如何覆盖它呢?
我还需要比较里面的hashMap吗?

我很困惑。该对象的唯一独特之处在于 myMap map ,它在生命周期的后期被填充。

我如何检查它的相等性?

根据所有回复,我将方法更改为以下

 @Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

final MyComplexObj myComplexObj = (MyComplexObj) o;

return myMap != null ? myMap.equals(myComplexObj.myMap) : myComplexObj.myMap == null;
}

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



public int compareTo(MyComplexObj o) {
return myMap.compareTo(o.getMyMap()));
}

这在 compareTo 方法处失败,“此方法对于类型 Map 是未定义的”

最佳答案

这里的基本问题是“如何确定两个对象是否相等?”

这是一个针对简单对象的简单问题。然而,即使是稍微复杂一点的物体也变得越来越困难。

如原问题所述:

The only unique thing about the object is the the map myMap which gets populated later in the lifecycle.

给定类型的两个实例 MyObject , 成员变量 myMap必须相互比较。这张 map 的类型是 Map<String, String> .立即想到几个问题:

  • 键和值如何定义相等性?
    • (键=值对是否需要作为一个单元进行比较?)
    • (或者应该只比较值?)
  • 映射中键的顺序如何影响相等性?
    • (列表中的键是否应该排序,以便 A-B-C 等同于 B-C-A?)
    • (或者 1-2-3 与 3-2-1 有什么不同的意思吗?)
  • 大写/小写对值的相等性有什么不同吗?
  • 这些对象是否会存储在某种 Java HashSet 中?或 Java TreeSet
    • (是否需要在同一个集合中多次存储同一个对象?)
    • (或者具有相同哈希码的对象是否应该只存储一次?)
  • 这些对象是否需要作为列表的一部分进行排序或 Java Collection
  • 比较函数应该如何排列列表中不相等的对象?
    • (键顺序应该如何确定一个对象在列表中出现在前面还是后面?)
    • (值应如何确定顺序,尤其是当多个值不同时?)

每个问题的答案因应用程序而异。为了使其适用于一般受众,做出以下假设:

  • 为了保持确定性比较,键将被排序
  • 值将被视为区分大小写
  • 键和值是不可分割的,将作为一个单元进行比较
  • Map 将被展平为单个字符串,因此可以轻松比较结果

使用之美equals() , hashCode() , 和 compareTo()是那一次hashCode()实现得当,其他功能可以根据hashCode()定义.

考虑到所有这些,我们有以下实现:

@Override
public boolean equals(final Object o)
{
if (o instanceof MyObject)
{
return (0 == this.compareTo(((MyObject) o)));
}
return false;
}

@Override
public int hashCode()
{
return getKeyValuePairs(this.myMap).hashCode();
}

// Return a negative integer, zero, or a positive integer
// if this object is less than, equal to, or greater than the other object
public int compareTo(final MyObject o)
{
return this.hashCode() - o.hashCode();
}

// The Map is flattened into a single String for comparison
private static String getKeyValuePairs(final Map<String, String> m)
{
final StringBuilder kvPairs = new StringBuilder();

final String kvSeparator = "=";
final String liSeparator = "^";

if (null != m)
{
final List<String> keys = new ArrayList<>(m.keySet());
Collections.sort(keys);

for (final String key : keys)
{
final String value = m.get(key);
kvPairs.append(liSeparator);
kvPairs.append(key);
kvPairs.append(kvSeparator);
kvPairs.append(null == value ? "" : value);
}
}

return 0 == kvPairs.length() ? "" : kvPairs.substring(liSeparator.length());
}

所有关键工作都在 hashCode() 内部完成.对于排序,compareTo()函数只需要返回一个负数/零/正数——一个简单的 hashCode()差异。和 equals()函数只需要返回 true/false——一个简单的检查 compareTo()等于零。


为了进一步阅读,Lewis Carroll 关于逻辑基础的著名对话涉及平等的基本问题:

https://en.wikipedia.org/wiki/What_the_Tortoise_Said_to_Achilles

而且,即使是简单的语法结构,在 chapter 6, "Pig and Pepper" 的开头也有两个“相等”句子的好例子。 ,来自爱丽丝梦游仙境:

The Fish-Footman began by producing from under his arm a great letter, and this he handed over to the other, saying, in a solemn tone, "For the Duchess. An invitation from the Queen to play croquet." The Frog-Footman repeated, in the same solemn tone, "From the Queen. An invitation for the Duchess to play croquet." Then they both bowed low and their curls got entangled together.

关于java - 如何覆盖 HashSet 的 equals()、hashcode() 和 compareTo(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44596224/

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