Collection集合的概念和常用方法分析-为什么要重写equals方法

1. Collection集合

集合是Java中的一种容器,可以存储多个数据,类似于数组,但是和数组又不一样

数组:存放元素的数据类型要相同;

存储元素的长度一定

集合:动态的存储多个对象

        动态:支持动态扩容

对象:存储类的实例,当存储基本数据类型时也会变为包装类对象

2. Collection常用的方法

集合的contains、equals、remove方法底层都是调用了元素对象的equals方法进行比较执行的。

add、addAll:添加元素方法

/**
 * 自定义类
 */
class Person {}

Collection col1 = new ArrayList();
// 因为没有指定集合中的数据类型,则默认为Object,如果传入666,则会发生向上转型:int->Integer->Object
col1.add(666);
col1.add(true);
col1.add("abc");
col1.add(new Person());

Collection col2 = new ArrayList();
col2.add(1);
col2.add(2);
col2.add(new Person());

col1.addAll(col2);
// 集合重写了toString方法,可以直接打印
System.out.println("col1: " + col1);


//结果
col1: [666, true, abc, com.study.part3.Person@2b, 1, 2, com.study.part3.Person@2b]

clear:清空集合

Collection col1 = new ArrayList();
// 因为没有指定集合中的数据类型,则默认为Object,如果传入666,则会发生向上转型:int->Integer->Object
col1.add(666);
col1.add(true);
col1.add("abc");
col1.add(new Person(12));

Collection col2 = new ArrayList();
col2.add(1);
col2.add(2);
col2.add(new Person(12));

col1.addAll(col2);
// 集合重写了toString方法,可以直接打印
System.out.println("col1: " + col1);

// 清空集合
col1.clear();
System.out.println("clear之后的col1: " + col1);

// 结果
col1: [666, true, abc, com.study.part3.Person@2b, 1, 2, com.study.part3.Person@2b]
clear之后的col1: []

contains:是否包含某个元素

底层调用元素对象的equals方法进行比较

/**
 * 自定义类
 */
class Person {

    Integer age;

    public Person(Integer age) {
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return Objects.equals(age, person.age);
    }

    @Override
    public int hashCode() {
        return Objects.hash(age);
    }
}


Collection col1 = new ArrayList();
// 因为没有指定集合中的数据类型,则默认为Object,如果传入666,则会发生向上转型:int->Integer->Object
col1.add(666);
col1.add(true);
col1.add("abc");
col1.add(new Person(12));
// 集合重写了toString方法,可以直接打印
System.out.println("col1: " + col1);

// 是否包含某个元素,如果集合中有引用类型,则会调用引用类型的equals方法进行内容比较
boolean contains = col1.contains("abc");
System.out.println("是否包含abc: " + contains);
// 如果没有重写equals方法,则equals方法默认比较的是内存地址,则就会返回false
boolean contains2 = col1.contains(new Person(12));
System.out.println("是否包含12岁的Person: " + contains2);

// 结果
col1: [666, true, abc, com.study.part3.Person@2b]
是否包含abc: true
是否包含12岁的Person: true

remove:移除某个元素,只会移除匹配到的第一个元素,即使存在多个相同元素,也只会移除一个

底层调用元素对象的equals方法进行比较

/**
 * 自定义类
 */
class Person {

    Integer age;

    public Person(Integer age) {
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return Objects.equals(age, person.age);
    }

    @Override
    public int hashCode() {
        return Objects.hash(age);
    }
}


Collection col1 = new ArrayList();
// 因为没有指定集合中的数据类型,则默认为Object,如果传入666,则会发生向上转型:int->Integer->Object
col1.add(666);
col1.add(true);
col1.add("abc");
col1.add(new Person(12));

Collection col2 = new ArrayList();
col2.add(1);
col2.add(2);
col2.add(new Person(12));

col1.addAll(col2);
// 集合重写了toString方法,可以直接打印
System.out.println("col1: " + col1);

// 移除某个元素,底层也是调用了对象的equals方法进行比较,只会移除匹配的第一个元素,即使集合中有多个相同元素,也只会移除一个
boolean remove = col1.remove(new Person(12));
System.out.println("是否移除成功: " + remove);
System.out.println(col1);

// 结果
col1: [666, true, abc, com.study.part3.Person@2b, 1, 2, com.study.part3.Person@2b]
是否移除成功: true
[666, true, abc, 1, 2, com.study.part3.Person@2b]


equals:如果和集合进行比较,则比较的就是集合中的元素内容是否相等

底层调用元素对象的equals方法进行比较

/**
 * 自定义类
 */
class Person {

    Integer age;

    public Person(Integer age) {
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return Objects.equals(age, person.age);
    }

    @Override
    public int hashCode() {
        return Objects.hash(age);
    }
}

Collection col2 = new ArrayList();
col2.add(1);
col2.add(2);
col2.add(new Person(12));

// 比较两个集合是否相等,比较的是元素内容。如果集合中有引用类型,则会调用引用类型的equals方法进行内容比较
Collection col3 = new ArrayList();
col3.add(1);
col3.add(2);
col3.add(new Person(12));
boolean equals = col2.equals(col3);
// 因为重写了Person类的equals方法,所以为true,若不重写,则比较的是每个元素的内存地址,则person这个元素肯定不相等,则就会返回false
System.out.println("比较两个集合是否相等: " + equals);

// 结果
比较两个集合是否相等: true

3. 源码剖析-集合对equals方法的使用

contains方法:

public boolean contains(Object o) {
  return indexOf(o) >= 0;
}

进入indexOf方法

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++)
            // 调用元素对象的equals方法进行比较,如果相同则返回对应的索引位置
            if (o.equals(elementData[i]))
                return i;
    }
    return -1;
}

remove方法:

public boolean remove(Object o) {
    if (o == null) {
        for (int index = 0; index < size; index++)
            if (elementData[index] == null) {
                fastRemove(index);
                return true;
            }
    } else {
        for (int index = 0; index < size; index++)
            if (o.equals(elementData[index])) {
                fastRemove(index);
                return true;
            }
    }
    return false;
}

总结:

Collection集合中的remove方法和contains方法底层都会调用equals;因为对对象的地址的比较没有什么意义,我们实际上需要的是对象内容间的比较;所以在有一些情况下我们就需要重写equals方法。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值