java list集合中contain()方法详解--解决我们在使用时多属性对象实例判断一直返回false 困扰bug问题

当我list集合为List<string> list  时候当我们

测试如下代码返回:

List<String> liststring=new ArrayList<>();
        liststring.add("张三");
        liststring.add("李四");
        String string="李四";
        if (liststring.contains(string)) {
            System.out.println("true  list中包含 string");
        }else {
            System.out.println("false  list中不包含 string");
        }

 

答应结果如下:说明此时contain()可以判断当前list集合存在已有的string对象

但是当list为List<User> listUser = new ArrayList<User>();

user对象为:

public class User  {
	private String name;
    
    private Integer age;

    
	public User() {
		super();
	}


	public User(String name, Integer age) {
		super();
		this.name = name;
		this.age = age;
	}


	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}
   
}

测试如下代码:

List<User> listUser = new ArrayList<User>();
		User user1 = new User("张三",18);
		listUser.add(user1);
		User user2 = new User("李四",19);
		listUser.add(user2);
		User user3 = new User("王五",20);
		listUser.add(user3);
		User user4 = new User("赵六",21);
		listUser.add(user4);
		System.out.println(listUser);		//创建一个LIst<User>对象数组 
		User user5 = new User("张三",18);	//张三 130 是否在List<User>中   在这个数组中返回true  没有返回false
		
		if(listUser.contains(user5)){
			System.out.println(true);
		}else{
			System.out.println(false);
		}

返回:

明明user5和user1是一样的,按道理是相等的,但是返回的结果为false 苦恼了我很久

 

没有办法只能看看list.contain()方法的底层源代码:

public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }
 
   /*
     * Returns the index of the first occurrence of the specified element
     * in this list, or -1 if this list does not contain the element.
     * More formally, returns the lowest index <tt>i</tt> such that
     * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>,
     * or -1 if there is no such index.
*/
     
    public int indexOf(Object o) {
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

底层就是遍历list然后依次与所需要判断的object做equal()方法比较

其实底层就是调用的user5.equal(object);

发现在contains方法会调用 o.equals(elementData[i])方法,其中elementData[i]是个object类的实例。也就是说我在调用list.contains(user)时实际上比较的是user.equals(object) 这当然会返回false。 

所有的对象都拥有标识(内存地址)和状态(数据),同时“==”比较两个对象的的内存地址,所以说使用Object的equals()方法是比较两个对象的内存地址是否相等,即若object1.equals(object2)为true,则表示equals1和equals2实际上是引用同一个对象。虽然有时候Object的equals()方法可以满足我们一些基本的要求,但是我们必须要清楚我们很大部分时间都是进行两个对象的比较,这个时候Object的equals()方法就不可以了,实际上JDk中,String、Math等封装类都对equals()方法进行了重写。(引用别人的话)

1.当两个string对象值时:由于生成string对象的优先常量池判断原则,两个string对象值相等其所在常量池中地址相同

所以调用equal() 可以返回true

2.当为非string类型object判断

不同的对象对应值相同,但是对应的内存地址不同调用equal()返回为false;

 

因此要解决我们头疼的问题:

重写equal()方法:

则user实体类重写equal方法如下:

@Override
	public boolean equals(Object obj) {
		if (obj instanceof User) {
			User user=(User) obj;
			if (this.age.equals(user.age)&&this.name.equals(user.name)) {
				return true;
			}else {
				return false;
			}
		}else {
			return false;
		}
	}

其中 :instanceof 为:

instanceof
instanceof是Java中的二元运算符,左边是对象,右边是类;当对象是右边类或子类所创建对象时,返回true;否则,返回false。

这里说明下:

类的实例包含本身的实例,以及所有直接或间接子类的实例

instanceof左边显式声明的类型与右边操作元必须是同种类或存在继承关系,也就是说需要位于同一个继承树,否则会编译错误
 

重新测试判断:

返回结果为:

现在大功告成,成功返回true;

 

所以当以后需要进行对象判断是需要自定义 重写object中的equal() 方法;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章