• ArrayList和HashSet的Contains()方法(转)


    来源: ArrayList和HashSet的Contains()方法

    笔试题:

    package com.champion.test.exam;
    
    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
    主要原因为:
    ArrayList和HashSet 的contains的 底层的实现不同

    ArrayList的contains

    public boolean contains(Object o) {  
      
      return indexOf(o) >= 0;  
      
    } 
    
    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()

    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 方法的常规协定:相同的对象必须具有相等的哈希码。

  • 相关阅读:
    系统边界确定
    用例分析技术:确定系统边界
    系统边界的定义
    【转】读《程序员修炼之道》
    项目管理之需求基线管理
    字符串流sstream[part3/使用字符串流进行安全的类型转换]
    字符串流sstream[part2/使用同一个字符串流反复读写数据]
    字符串流sstream[part1/基本知识]
    文件操作的openmode
    文件操作的一些函数
  • 原文地址:https://www.cnblogs.com/cuiyf/p/6215015.html
Copyright © 2020-2023  润新知