【问题标题】:comparing the content of two HashMaps with set<> value将两个 HashMap 的内容与 set<> 值进行比较
【发布时间】:2024-01-11 04:49:01
【问题描述】:

我有这两个对象。

public Map<String, Set<RuleConditionBl>> countryToNonSplittedRules1 = new HashMap<>;
public Map<String, Set<RuleConditionBl>> countryToNonSplittedRules2 = new HashMap<>;

我有一个比较这两个的测试

即使他们的内容是相同的,我也得到了错误的

countryToNonSplittedRules1.equals(countryToNonSplittedRules2);

这是一个例子:

我读过这个post,所以我不确定为什么不返回true

public class RuleConditionBl {

public int weight;
public boolean isAll;
public List<String> countries;
public UserFlag userFlag;

@JsonIgnore
private Range<LocalDate> datesRange;

public String fromDate;
public String toDate;

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

        RuleConditionBl that = (RuleConditionBl) o;

        if (weight != that.weight) return false;
        if (isAll != that.isAll) return false;
        if (countries != null ? !countries.equals(that.countries) : that.countries != null) return false;
        if (userFlag != that.userFlag) return false;
        return datesRange != null ? datesRange.equals(that.datesRange) : that.datesRange == null;
    }

    @Override
    public int hashCode() {
//        int result = weight;
        int result = 0;
        result = 31 * result + (isAll ? 1 : 0);
        result = 31 * result + (countries != null ? countries.hashCode() : 0);
        result = 31 * result + (userFlag != null ? userFlag.hashCode() : 0);
        result = 31 * result + (datesRange != null ? datesRange.hashCode() : 0);
        return result;
    }

{

【问题讨论】:

  • 在您的屏幕截图中没有观察到的一件事:您确定这些国家/地区是平等的吗?为了更容易调试:为什么不添加一个漂亮的 toString() 并打印出两个映射的内容?
  • 你为什么要删除你的其他问题? 再次hashCode 中应包含权重。
  • 您不应将 UserFlag 实例与 userFlag != that.userFlag 进行比较(即使在您的示例中两者都为空,因此不应影响结果)。使用等于
  • 权重可能会包含在哈希码中以确保完整性,但省略并不是失败的原因。您可以将 hashCode 始终设置为 1 并且它应该仍然可以工作,只要 equals 定义正确。如果它不是枚举,我会更担心 userFlag - 但由于在这种情况下它为空,所以这不是问题。我建议启动一个调试器,添加断点并逐行执行 RuleConditionB1 的 equals 方法,看看它会从哪里退出。
  • 如果您正在检查UserFlag 的相等性,您应该使用equals 方法,如果UserFlag 某些具有自己属性的对象也应该实现equalshashcode 方法。

标签: java hashmap set equals


【解决方案1】:

我看过你的解决方案。

你的实现是正确的(ish)。

首先,如果我没记错的话,Range&lt;LocalDate&gt; datesRange 应该不起作用。 Range 不是通用的,因此不能用参数进行参数化。(如果我错了,请纠正我)。

我将Range&lt;LocalDate&gt; datesRange 更改为List&lt;LocalDate&gt; datesRange

除此之外,您的代码是正确的。我认为您的问题是将对象放入countryToNonSplittedRules1countryToNonSplittedRules2 时的关键值。键值必须相同,否则无法比较两张地图。

Map<String, Set<RuleConditionBl>> countryToNonSplittedRules1 = new HashMap<>();
Map<String, Set<RuleConditionBl>> countryToNonSplittedRules2 = new HashMap<>();


Set<RuleConditionBl> s1 = new LinkedHashSet<>();
Set<RuleConditionBl> s2 = new LinkedHashSet<>();

//Objects for s1
RuleConditionBl r1 = new RuleConditionBl();
r1.weight = 710;
r1.userFlag = null;
r1.isAll = false;

RuleConditionBl r3 = new RuleConditionBl();
r3.weight = 700;
r3.userFlag = null;
r3.isAll = false;

s1.add(r1);
s1.add(r3);

countryToNonSplittedRules1.put("r1", s1);

//Objects for s2
RuleConditionBl r2 = new RuleConditionBl();
r2.weight = 700;
r2.userFlag = null;
r2.isAll = false;

RuleConditionBl r4 = new RuleConditionBl();
r4.weight = 710;
r4.userFlag = null;
r4.isAll = false;

s2.add(r2);
s2.add(r4);

countryToNonSplittedRules2.put("r1", s2);

System.out.println(countryToNonSplittedRules1.equals(countryToNonSplittedRules2));

输出:

true

Set 中元素的顺序很重要。根据文档:

比较指定对象与此集合是否相等。返回真 如果给定对象也是一个集合,则这两个集合具有相同的大小, 并且给定集合的每个成员都包含在该集合中。这个 确保 equals 方法在不同的应用程序中正常工作 Set 接口的实现。

【讨论】:

  • 好吧,为我自己评论。我导入的 Range 可能与 OP 使用的导入不同,这就是为什么他可以参数化 Range 与争论。