开发者社区> 问答> 正文

关于list集合和set集合的问题

请问各位大牛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

展开
收起
蛮大人123 2016-03-10 17:27:52 2346 0
1 条回答
写回答
取消 提交回答
  • 我说我不帅他们就打我,还说我虚伪

    我查了下源码,我觉得HashSet的Hash这里有文章。
    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&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;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过程中也少不了这个环节的。
    再来看比较的情况
    //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&nbsp;?&nbsp;e==null&nbsp;:&nbsp;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;
        }

    结论
    插入HashSet容器时对元素做哈希,判断容器是否含有某个元素时也要对元素做哈希,他们比较的是元素的哈希值。

    2019-07-17 18:58:00
    赞同 展开评论 打赏
问答标签:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载