List删除指定元素以及List删除与另一List相同元素的方法

 List删除指定元素

在List类中,提供了删除元素的remove()方法,有如下两种传参方式

    1.根据index删除,会删除指定位置的元素,源码如下

public E remove(int index) {
    try {
        ListIterator<E> e = listIterator(index);
        E outCast = e.next();
        e.remove();
        return outCast;
    } catch (NoSuchElementException exc) {
        throw new IndexOutOfBoundsException("Index: "+index);
    }
}

    2.根据对象删除 ,源码如下,该方法使用equals方法判断是否为要删除的对象,经测试,使用list.remove(object)方法后,仅删除集合中第一个满足条件的元素

public boolean remove(Object o) {
    Iterator<E> it = iterator();
    if (o==null) {
        while (it.hasNext()) {
            if (it.next()==null) {
                it.remove();
                return true;
            }
        }
    } else {
        while (it.hasNext()) {
            if (o.equals(it.next())) {
                it.remove();
                return true;
            }
        }
    }
    return false;
}

根据上述提到的两种方法,可以对List中元素进行删除,但是当需要删除的元素不止一个时,需要循环删除元素,就会产生一些问题

    1.采用for循环由小到大删除时,采用remove(int index)方法,会出现指针越界异常。因为移除List中的一个元素后,List长度会减少,但for循环的次数仍是原本List的长度

for(int i = 0,j = numberList.size();i < j;i++){
            if(numberList.get(i).equals(element)){
                numberList.remove(element);
            }
        }

//异常如下
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 11, Size: 10
	at java.util.LinkedList.checkElementIndex(LinkedList.java:555)
	at java.util.LinkedList.get(LinkedList.java:476)
	at com.Test.ListTest.main(ListTest.java:29)

    2.当使用Iterator迭代器或是增强for循环遍历数组时,采用remove(Objec o)移除元素时,仍然会出现异常。因为执行 该方法后,对 list 对象的 modCount 值进行了修改,而 list 对象的迭代器的 expectedModCount 值未进行修改

for(Long l : numberList){
            if(l.equals(element)){
                numberList.remove(element);
            }
        }
 Iterator iterator = numberList.iterator();
        while (iterator.hasNext()){
            if(iterator.next().equals(element)){
                numberList.remove(element);
            }
        }
//异常如下
Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:966)
	at java.util.LinkedList$ListItr.next(LinkedList.java:888)
	at com.Test.ListTest.main(ListTest.java:22)

正确的删除方式有三种:

   1.正序for循环删除,由于删除后List中的元素会前移一位,所以我们首先i--将指针移到被前移的元素上,再将数组长度-1,防止指针越界

        for(int i = 0,j = numberList.size();i < j;i++){
            if(numberList.get(i).equals(element)){
                numberList.remove(element);
                j--;
                i--;
            }
      

    2.倒序for循环删除,List由最后一位向前循环,每次移除元素,指针都会前移一位,总移动次数也与数组长度相同

        for(int i= numberList.size()-1;i >= 0;i--){
            if(numberList.get(i).equals(element)){
                numberList.remove(element);
            }
        }

3.迭代器删除,该方法与错误迭代器方法的不同就是需要采用迭代器的remove()方法,而不是List中的remove(Object o)方法

        Iterator iterator = numberList.iterator();
        while (iterator.hasNext()){
            if(iterator.next().equals(element)){
                iterator.remove();
            }
        }

List删除与另一List相同元素的方法

    上面说完了简单情况下的List循环删除,实际开发中情况可能更为复杂,需要根据两集合中,元素同名同类型属性值相同,去移除其中一个集合中的元素

    1.有集合a和集合b,现在需要将a从移除a与b的子集,如果集合中的元素可以用"=="或者"equals()"方法判定是否相同,那么可以使用List中提供的removeAll(Collection c)方法,该方法可以将a中的a与b子集含有的元素全部删除,缺点是执行效率较低

        //生成1-100的随机数,集合a
        List<Long> numberList = new LinkedList<>();
        for(int i = 0 ; i < 10 ; i++){
            numberList.add((long)(Math.random()*100+1));
            numberList.add(10L);
        }

        Long element = 10L;

        //集合b
        List<Long> targetList = new LinkedList<Long>();
        targetList.add(element);

        numberList.removeAll(targetList);
        System.out.println(numberList);

    2.当情况更为复杂,无法使用equals()方法判断两元素是否相同,或者根据两元素各自的某项属性值判断是否需要移除时,则需要使用双重循环,逐条进行对比,为防止指针越界异常,当移除了元素后,需调整指针位置和循环次数。此处我使用倒序删除的方式,可以避免手动移动指针。值得注意的是:内层循环每次判断元素属性值相同,做移除操作后,必须中断循环,这样指针前移后,又重新循环集合b,避免漏删和空指针的情况。

for(int i = heroes.size()-1;i >= 0;i--){
            for(int j = idols.size()-1;j >=0;j--){
                if(heroes.get(i).getBrave() == idols.get(j).getBrave()){
                    heroes.remove(i);
                    break;
                }
            }
        }

//执行结果如下
集合a:
[Name:tom  Brave100, Name:tony  Brave50, Name:tony  Brave20, Name:tom  Brave100, Name:tony  Brave50, Name:tony  Brave20]
集合b:
[Name:kk  Brave20, Name:kk  Brave20, Name:cc  Brave50]
删除后的集合a:
[Name:tom  Brave100, Name:tom  Brave100]

   3.迭代器实现的方法,运行结果和上面for循环方法的结果相同,缺点是必须使用引用指向强转后的iterator.next(),优点是不用思考指针如何移动

        while (heroeIterator.hasNext()){
            while (idolIterator.hasNext()){
                Hero h = (Hero)heroeIterator.next();
                Idol i = (Idol)idolIterator.next();
                if(h.getBrave() == i.getBrave()){
                    heroeIterator.remove();
                }
            }
        }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值