ArrayList和HashSet中contains方法的不同

本文解析了ArrayList和HashSet中contains方法的区别,并通过一个示例程序详细阐述了这两种集合类型在处理自定义对象时的行为差异,强调了正确重写equals与hashCode方法的重要性。
摘要由CSDN通过智能技术生成

ArrayList和HashSet中contains方法的不同

首先来看一道笔试题:

view plaincopy to clipboardprint?import java.util.ArrayList; 
 
import java.util.HashSet; 
 
public class Foo { 
 
   int value; 
 
   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 int hashCode() {

         return this.value;

   }

*/ 
 
   public static void main(String... args) { 
 
      ArrayList list = new ArrayList(); 
 
      HashSet set = new HashSet(); 
 
       
 
      Foo f1 = new Foo(1); 
 
      Foo f2 = new Foo(1); 
 
      list.add(f1); 
 
      set.add(f2); 
 
       
 
      Foo f3 = new Foo(1); 
 
      Foo f4 = new Foo(1); 
 
      System.out.println(list.contains(f3) + "," + set.contains(f4)); 
 
   } 
 

import java.util.ArrayList;

import java.util.HashSet;

public class Foo {

   int value;

   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 int hashCode() {

         return this.value;

   }

*/

   public static void main(String... args) {

      ArrayList list = new ArrayList();

      HashSet set = new HashSet();

     

      Foo f1 = new Foo(1);

      Foo f2 = new Foo(1);

      list.add(f1);

      set.add(f2);

     

      Foo f3 = new Foo(1);

      Foo f4 = new Foo(1);

      System.out.println(list.contains(f3) + "," + set.contains(f4));

   }

}

答案:true,false   打开注释后,结果为:true ,true



下面分析为什么,我们先看看JDK中ArrayList的方法contains()的源代码:

view plaincopy to clipboardprint?public boolean contains(Object o) { 
 
      return indexOf(o) >= 0; 
 

public boolean contains(Object o) {

      return indexOf(o) >= 0;

}


其中调用了indexOf(),我们接着看,

view plaincopy to clipboardprint?public int indexOf(Object o) { 
 
if (o == null) { 
 
       for (int i = 0; i < size; i++) 
 
      if (elementData[i]==null) 
 
          return i;//如果o为空且集合中i位置处也为空,返回i  
 
   } else { 
 
       for (int i = 0; i < size; i++) 
 
      if (o.equals(elementData[i])) 
 
          return i;//如果o不为空,且集合中i位置对象equals对象o,返回i  
 
   } 
 
   return -1;//否则返回-1  
 

public int indexOf(Object o) {

if (o == null) {

       for (int i = 0; i < size; i++)

      if (elementData[i]==null)

          return i;//如果o为空且集合中i位置处也为空,返回i

   } else {

       for (int i = 0; i < size; i++)

      if (o.equals(elementData[i]))

          return i;//如果o不为空,且集合中i位置对象equals对象o,返回i

   }

   return -1;//否则返回-1

}


所以,因为list中有对象f1,而f1.equals(f3)为true,所以执行indexOf()方法返回0,执行contains()返回true;

在来看HashSet中contains()方法源代码:

view plaincopy to clipboardprint?public boolean contains(Object o) { 
 
      return map.containsKey(o); 
 

 
public boolean containsKey(Object key) { 
 
       return getEntry(key) != null; 
 

 
final Entry<K,V> getEntry(Object key) { 
 
        int hash = (key == null) ? 0 : hash(key.hashCode()); 
 
        for (Entry<K,V> e = table[indexFor(hash, table.length)]; 
 
             e != null; 
 
             ee = e.next) { 
 
            Object k; 
 
            if (e.hash == hash && 
 
                ((k = e.key) == key || (key != null && key.equals(k)))) 
 
                return e; 
 
        } 
 
       return null; 
 

public boolean contains(Object o) {

      return map.containsKey(o);

}

public boolean containsKey(Object key) {

       return getEntry(key) != null;

}

final Entry<K,V> getEntry(Object key) {

        int hash = (key == null) ? 0 : hash(key.hashCode());

        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;

}


由于Foo类中重写了equals()而没有重写hashCode()方法,所以会执行父类Object 中的 hashCode 方法,(会针对不同的对象返回不同的整数,具体是将该对象的内部地址转换成一个整数来实现的),由于f2和f4内存地址不同,所以hashcode也不同,所以执行getEntry()方法返回null,执行containsKey返回false,当然的执行contains()也会返回false;

综上所述:对于一个类重写了equals()方法后,重写它的hashCode()方法是必要的,以维护 hashCode 方法的常规协定:相同的对象必须具有相等的哈希码。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值