java.util.Set.contains(对象o)的怪异行为 [英] Weird behavior of java.util.Set.contains(Object o)

查看:150
本文介绍了java.util.Set.contains(对象o)的怪异行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

doc 关于 java.util.Set.contains(Object o)说:


当且仅当此集合包含元素e使得
(o == null?e == null:o.equals(e))时,返回true。

Returns true if and only if this set contains an element e such that (o==null ? e==null : o.equals(e)).

也就是说,这是一个POJO(如您所见,我重写了它的 equals 方法):

That said, here is a POJO (as you can see, I overwrote its equals method):

public class MonthAndDay {

    private int month;
    private int day;

    public MonthAndDay(int month, int day) {
        this.month = month;
        this.day = day;
    }

    @Override
    public boolean equals(Object obj) {
        MonthAndDay monthAndDay = (MonthAndDay) obj;
        return monthAndDay.month == month && monthAndDay.day == day;
    }

}

那么,为什么要执行以下操作代码显示 false 而不是 true

So please, why does the following code prints false instead of true?

Set<MonthAndDay> set = new HashSet<MonthAndDay>();
set.add(new MonthAndDay(5, 1));
System.out.println(set.contains(new MonthAndDay(5, 1)));
// prints false

一种解决方案是重写包含的内容(对象o)方法,但是原始方法应该(几乎)完全一样,我错了吗?

A solution is to rewrite the contains(Object o) method, but the original one should be (almost) exactly the same, am I wrong?

Set<MonthAndDay> set = new HashSet<MonthAndDay>() {

    private static final long serialVersionUID = 1L;

    @Override
    public boolean contains(Object obj) {
        MonthAndDay monthAndDay = (MonthAndDay) obj;
        for (MonthAndDay mad : this) {
            if (mad.equals(monthAndDay)) {
                return true;
            }
        }
        return false;
    }

};
set.add(new MonthAndDay(5, 1));
System.out.println(set.contains(new MonthAndDay(5, 1)));
// prints true


推荐答案

equals(Object),您还需要覆盖 hashcode()

具体来说,必须实现这些方法,以便如果 a.equals(b) true ,则 a.hashcode()== b.hashcode()都是 true 。如果不遵守此不变式,则 HashMap HashSet Hashtable 无法正常工作。

Specifically, the methods must be implemented so that if a.equals(b) is true, then a.hashcode() == b.hashcode() is all true. If this invariant is not respected, then HashMap, HashSet and Hashtable will not work properly.

hashcode()的技术细节在对象中指定了equals(Object)应该表现的行为 API。

The technical details of how hashcode() and equals(Object) should behave are specified in the Object API.

那么如果弄错了,为什么基于哈希的数据结构会中断?好吧,基本上是因为哈希表通过使用哈希函数的值来缩小要与候选进行比较的值的集合而起作用。如果候选人的哈希码与表中某个对象的哈希码不同,则即使对象相等,查找算法也可能无法与表中的对象进行比较。

So why do the hash-based data structures break if you get this wrong? Well basically because a hash table works by using the value of the hash function to narrow down the set of values to be compared with the "candidate". If the hashcode for the candidate is different to the hashcode for some object in the table, then the chances are that the lookup algorithm won't compare with the object in the table ... even if the objects are equal.

这篇关于java.util.Set.contains(对象o)的怪异行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆