Collection集合常用方法contains、remove详解

contains、remove方法解析
在开始这两个方法之前先浅谈一下迭代器

注意:以下讲解的遍历方式/迭代方式,是所有Collection通用的一种方式,在Map集合中不能使用。在所有的Collection以及子类中使用。

example:

// 创建集合对象
Collection c = new ArrayList(); 
// 添加元素
c.add("abc");
c.add("def");
c.add(100);
c.add(new Object());
// 对集合Collection进行遍历/迭代
// 第一步: 获取集合对象的迭代器对象 Iterator
Iterator it = c.iterator();
// 第二步: 通过以上获取的迭代器对象开始迭代/遍历集合
while(it.hasNext()){
    Object obj = it.next();
    System.out.println(obj);
}

运行结果:

abc
def
100
java.lang.Object@1b6d3586
迭代器原理:

迭代器可以理解为原集合的一个快照(照片),记录的是原集合某一个时间的状态(内容)。当利用迭代器去遍历元素时,它会先在它自身(迭代器)去查,自身查到以后再映射到集合上面去找,进而找到元素,相当于进行了两次查找(我的理解是迭代器只是存储了某一个时间集合中各元素的地址,利用迭代器去遍历元素时相当于先遍历出元素地址,再利用地址去映射(查找)到元素,相当于两次查找),利用迭代器删除元素也是同样的道理(进行两次删除)!迭代器的底层源码十分复杂,感兴趣的可以自己去看看!
在这里插入图片描述

1. contains方法

boolean contains(Object o)判断集合中是否包含某个对象o,如果包含返回true,如果不包含返回false。contains方法是用来判断集合中是否包含某个元素的方法,它的底层是调用了equals方法进行比对:equals方法返回true,就表示包含个某元素,否则表示不包含这个元素。

example1:

  		// 创建集合对象
        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());
        // 新建对的对象String
        String x = new String("abc");
        // c集合中是否包含x?结果猜测一下是true还是false?
        System.out.println(c.contains(x));

运行结果:

元素的个数:2
true

但如果代码是这样:

  		// 创建集合对象
        Collection c = new ArrayList();
        // 创建用户对象
        User u1 = new User("jack");
        User u2 = new User("jack");
        // 加入集合
        c.add(u1);
        System.out.println(c.contains(u2));
    }
}
class User{
    private String name;
    public User(){};
    public User(String name){
        this.name = name;
    }
}

运行结果:

false

这是怎么回事嘞?在example1中String对象中,输出结果为true,而在此处的例子中输出结果却为false。这是因为在User类中没有重写equals方法,故此时会调object类的equals方法,而object的equals方法是用==比较的内存地址,两个对象的内存地址肯定不相同,故输出结果为false!在上述User类中重写equals方法:

 	@Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        // 不在比较内存地址了,而是比较内容
        return Objects.equals(name, user.name);
    }

则输出结果为:

true

总而言之:重写equals方法是java程序员的基本素养

2. remove方法

其实remove方法的原理同contains方法的原理一样,也是需要重写equals方法!

example1:

  		// 创建集合
        Collection c = new ArrayList();
        Iterator it = c.iterator();
        // 添加元素
        c.add(1); 
        c.add(2);
        c.add(3);

        while(it.hasNext()){
            // 编写代码时next() 方法返回值类型必须是Object。
            Object obj = it.next();
            System.out.println(obj);
       }

运行结果:

	Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
	at java.util.ArrayList$Itr.next(ArrayList.java:859)
	at com.lxz.collection.CollectionTest06.main(CollectionTest06.java:36)

由example1的代码我们可以知道,是先获取了迭代器,然后再添加了元素,相当于集合中的元素发生了变化!此时就会报一个异常ConcurrentModificationException.迭代器可以理解为一个快照(照片),只是记录了某一个时间上的集合,故此例子中获取的迭代器实际上是没有任何元素的!一定要***注意***: 集合结构只要发生改变,迭代器必须重新获取,否则会出现.ConcurrentModificationException的异常

example2:

  		Collection c2 = new ArrayList();
        c2.add("abc");
        c2.add("def");
        c2.add("xyz");
        Iterator it2 = c2.iterator();
        while(it2.hasNext()){
            Object o = it2.next();
            c2.remove(o); 
            System.out.println(o);
        }
        System.out.println(c2.size()); 

运行结果:

abc
Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
	at java.util.ArrayList$Itr.next(ArrayList.java:859)
	at com.lxz.collection.CollectionTest06.main(CollectionTest06.java:45)

example2通过迭代器去遍历出每一个元素,然后再调用集合自身的remove方法去删除集合中的元素!这样会报ConcurrentModificationException异常,因为元素删除之后,没有更新迭代器(迭代器不知道集合变化了),导致迭代器的快照与原集合状态不同!故当集合的状态发生变化以后需要去重新获取迭代器!

example3:

	Collection c2 = new ArrayList();
    c2.add("abc");
    c2.add("def");
    c2.add("xyz");
    Iterator it2 = c2.iterator();
    while(it2.hasNext()){
        Object o = it2.next();
        it2.remove(o); 
        System.out.println(o);
    }
    System.out.println(c2.size()); 

运行结果:

abc
def
xyz
0

使用迭代器的remove方法去删除元素时,会自动更新迭代器,并且更新集合(删除集合中的元素)!不会导致迭代器的快照与原集合状态不同!也就是说,集合的remove方法删除,只会删除集合本身中的元素。而使用迭代器的remove方法删除元素时,会将迭代器和原集合中的元素都删除!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鹤林村菠萝皮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值