关于list集合和set集合的问题请大神指导一下

发布于 2022-09-02 01:21:02 字数 832 浏览 13 评论 0

请问各位大牛list和set调用contains方法时是比较两个元素的地址,还是调用他们的equals方法呢?

public class Foo {
    int value;
    public Foo(int value) {
        this.value = value;
    }
    public boolean equals(Object obj) {
        if (obj instanceof Foo) {
            Foo foo = (Foo) obj;
            return value == foo.value;
        } else {
            return false;
        }
    }
    public static void main(String[] args) {
        //运行下面程序段:
        ArrayList list = new ArrayList();
        HashSet set = new HashSet();
        list.add(new Foo(1));
        set.add(new Foo(1));
        System.out.println(list.contains(new Foo(1)) + ","+ set.contains(new Foo(1)));
        //或者
        System.out.println(new Foo(1).equals (new Foo(1)) + ","+ set.contains(new Foo(1)));     
    }
}

我想问的就是为什么这个输出的结果是true,false

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

爱的十字路口 2022-09-09 01:21:02

我查了下源码,我觉得HashSetHash这里有文章。

  • 1.首先看添加元素的过程
    //HashSet代码

    /**
     * Adds the specified element to this set if it is not already present.
     * More formally, adds the specified element <tt>e</tt> to this set if
     * this set contains no element <tt>e2</tt> such that
     * <tt>(e==null ? e2==null : e.equals(e2))</tt>.
     * If this set already contains the element, the call leaves the set
     * unchanged and returns <tt>false</tt>.
     *
     * @param e element to be added to this set
     * @return <tt>true</tt> if this set did not already contain the specified
     * element
     */
    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }

HashSet内部维护的map添加新元素
//HashMap代码

    /**
     * Associates the specified value with the specified key in this map.
     * If the map previously contained a mapping for the key, the old
     * value is replaced.
     *
     * @param key key with which the specified value is to be associated
     * @param value value to be associated with the specified key
     * @return the previous value associated with <tt>key</tt>, or
     *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
     *         (A <tt>null</tt> return can also indicate that the map
     *         previously associated <tt>null</tt> with <tt>key</tt>.)
     */
    public V put(K key, V value) {
        if (table == EMPTY_TABLE) {
            inflateTable(threshold);
        }
        if (key == null)
            return putForNullKey(value);
        int hash = hash(key);
        int i = indexFor(hash, table.length);
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }

        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }

可以看出会对Element做哈希,所以如果添加Foo(1)的话,保存到HashSet过程中也少不了这个环节的。

    1. 再来看比较的情况
      //HashSet代码

    /**
     * Returns <tt>true</tt> if this set contains the specified element.
     * More formally, returns <tt>true</tt> if and only if this set
     * contains an element <tt>e</tt> such that
     * <tt>(o==null ? e==null : o.equals(e))</tt>.
     *
     * @param o element whose presence in this set is to be tested
     * @return <tt>true</tt> if this set contains the specified element
     */
    public boolean contains(Object o) {
        return map.containsKey(o);
    }

//HashMap代码

    /**
     * Returns <tt>true</tt> if this map contains a mapping for the
     * specified key.
     *
     * @param   key   The key whose presence in this map is to be tested
     * @return <tt>true</tt> if this map contains a mapping for the specified
     * key.
     */
    public boolean containsKey(Object key) {
        return getEntry(key) != null;
    }
    /**
     * Returns the entry associated with the specified key in the
     * HashMap.  Returns null if the HashMap contains no mapping
     * for the key.
     */
    final Entry<K,V> getEntry(Object key) {
        if (size == 0) {
            return null;
        }

        int hash = (key == null) ? 0 : hash(key);
        for (Entry<K,V> e = table[indexFor(hash, table.length)];
             e != null;
             e = e.next) {
            Object k;
            if (e.hash == hash &&
                ((k = e.key) == key || (key != null && key.equals(k))))
                return e;
        }
        return null;
    }
    1. 结论
      插入HashSet容器时对元素做哈希,判断容器是否含有某个元素时也要对元素做哈希,他们比较的是元素的哈希值。

执着的年纪 2022-09-09 01:21:02

equals的方法,但是值得注意的是二楼说的是String下的equals方法,因为String的equals方法是重写过的,如果题主希望通过contains方法对于一般Object的比较的话,还是得和String一样重写equals方法,确定何种规则

じее 2022-09-09 01:21:02
    public boolean contains(Object o) {
    Iterator<E> it = iterator();
    if (o==null) {
        while (it.hasNext())
            if (it.next()==null)
                return true;
    } else {
        while (it.hasNext())
            if (o.equals(it.next()))
                return true;
    }
    return false;
}

这个是AbstractCollection的实现, AbstractList, AbstractSet都是以此为父类实现的.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文