Java中Collection中的contains方法深度解析

一、问题提出:

众所周知,Java集合的contains方法是判断某个元素在集合中是否存在。
boolean contains(Object o)判断集合中是否包含某个对象o。如果包含返回true,不包含则返回false。但是contains底层原理是个值得深究的问题

二、问题深入:

1、经典例子:

import java.util.ArrayList;
import java.util.Collection;

public class CollectionTest04 {
    public static void main(String[] args) {
        //创建集合对象
        Collection c = new ArrayList();

        //向集合中存储元素
        String s1 = new String("abc");
        c.add(s1);

        String s2 = new String("def");
        c.add(s2);

        //集合中元素个数
        System.out.println("元素个数是:" + c.size());//2

        //新建对象String
        String x = new String("abc");
        //c集合中是否包含x
        System.out.println(c.contains(x));
    }
}

上述执行结果为true。在这里读者可能会怀疑:为什么第三个字符串对象是后来创建的,却包含在集合中?这里要介绍一下JVM创建String对象的问题

2、JVM问题:

这里介绍一下JVM的内存问题:
在这里插入图片描述
如图所示,虽然创建了另一个对象x,但这个对象会去方法区的字符串常量池中寻找与自己“内容”相同的对象,如果找到,那么两个不同内存地址的String字符串对象就会在字符串常量池中指向同一个存储单元。
听着很熟悉是不是?没错,这就是equals方法。可能有读者会问,这里没有重写equals方法,为什么内存地址不同的对象还能够指向同一个字符串呢?
这里拓展一下:

3、String和自定义数据类型的比较:

(1)下面我们先自定义一个数据类型,并加上Collection:
import java.util.ArrayList;
import java.util.Collection;

/*
测试contains方法
结论:存放在集合中的类型一定要重写equals方法
 */
 
//没有重写equals方法
class User{
    private String name;
    public User() { }
    public User(String name) { this.name = name; }
}

public class CollectionTest05 {
    public static void main(String[] args) {
        Collection c = new ArrayList();
        //创建用户对象
        User u1 = new User("jack");
        User u2 = new User("jack");
        //加入集合
        c.add(u1);
        //判断集合中是否包含u2
        System.out.println(c.contains(u2));
    }
}

//p199

这段代码执行结果就为false。那么为什么User数据类型和String不同呢
(1)String底层已对equals进行重写,所以两个字符串比较的是字符串本身的内容,而不是内存地址
(2)由于创建对象的不是String而是User,所以没有重写equals方法。contains要调用equals方法,所以会调用Object中的equals方法
(3)而不经重写的equals方法比较的是内存地址,所以结果是false

(2)这里要对equals方法进行重写:
public boolean equals(Object o ) {
        if (o == null || !(o instanceof User)) return false;
        if (o == this) return true;
        User u = (User) o; //强制类型转换,把o转换为u
        return u.name.equals(this.name);
    }

这样一来,代码执行结果就为true了

三、总结:

contains底层调用了equals方法,但这个方法依赖于集合中的数据类型,如果数据类型底层已经重写了该方法,那么就不用对equals进行override。
所以,养成重写equals方法的习惯是程序员的基本素质。

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值