如何从List集合中删除对象

news/2024/7/4 1:20:06 标签: list, exception, 多线程, import, string, class
class="baidu_pl">
class="article_content clearfix">
class="htmledit_views">

这个问题看似好像挺简单挺幼稚的,然而就这个幼稚的问题还曾经困扰过我一阵呢,其实犯这个错误的根本原因是我们对于基础知识的理解和掌握上还有不足的表现,基本功有些人总是觉得不重要,认为更多的扩大学习的广度才是最重要的,我认为这是很容易犯的,同时也是很致命的错误观点!

对基础知识掌握不牢靠,或理解不深刻,写出的代码必然会有40%的概率是错误的、低效的,一段代码不是说没有编译错误就一定是对的,不是说简单的运行下就一定是对的,优秀的代码,是经得起“刀山火海”般的考验的(“class="tags" href="/tags/DuoXianCheng.html" title=多线程>多线程、效率、安全”这三坐大山)。

所以重要性,我就不再强调了,相信说完后,地球人都能懂我的意思,那么下面就来看看这个有趣的现象吧。


先看看如下代码

class="language-java">class="tags" href="/tags/IMPORT.html" title=import>import java.util.ArrayList;
class="tags" href="/tags/IMPORT.html" title=import>import java.util.Iterator;
class="tags" href="/tags/IMPORT.html" title=import>import java.util.List;

public class TestList {

	void init(List<Integer> class="tags" href="/tags/LIST.html" title=list>list) {
		class="tags" href="/tags/LIST.html" title=list>list.clear();
		for (int i = 0; i < 10; i++) {
			class="tags" href="/tags/LIST.html" title=list>list.add(i + 1);
		}
	}

	void remove(List<Integer> class="tags" href="/tags/LIST.html" title=list>list) {
		for (int i = 0; i < 5; i++) {
			class="tags" href="/tags/LIST.html" title=list>list.remove(i);
		}
	}

	void removeTwo(List<Integer> class="tags" href="/tags/LIST.html" title=list>list) {
		for (int i : class="tags" href="/tags/LIST.html" title=list>list) {
			if (i < 6) {
				class="tags" href="/tags/LIST.html" title=list>list.remove(i);
			}
		}
	}

	void removeThree(List<Integer> class="tags" href="/tags/LIST.html" title=list>list) {
		for (Iterator<Integer> iter = class="tags" href="/tags/LIST.html" title=list>list.iterator(); iter.hasNext();) {
			int i = iter.next();
			if (i < 6) {
				iter.remove();
			}
		}
	}

	public static void main(String[] args) {
		TestList testList = new TestList();
		List<Integer> class="tags" href="/tags/LIST.html" title=list>list = new ArrayList<Integer>();

		// 第一种方法
		testList.init(class="tags" href="/tags/LIST.html" title=list>list);
		testList.remove(class="tags" href="/tags/LIST.html" title=list>list);
		System.out.println(class="tags" href="/tags/LIST.html" title=list>list);

		// 第二种方法
		try {
			testList.init(class="tags" href="/tags/LIST.html" title=list>list);
			testList.removeTwo(class="tags" href="/tags/LIST.html" title=list>list);
			System.out.println(class="tags" href="/tags/LIST.html" title=list>list);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		// 第三种方法
		testList.init(class="tags" href="/tags/LIST.html" title=list>list);
		testList.removeThree(class="tags" href="/tags/LIST.html" title=list>list);
		System.out.println(class="tags" href="/tags/LIST.html" title=list>list);
	}
}

运行的结果如下:

[2, 4, 6, 8, 10]

java.util.ConcurrentModificationException

at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)

at java.util.AbstractList$Itr.next(AbstractList.java:343)

at com.TestList.removeTwo(TestList.java:23)

at com.TestList.main(TestList.java:60)

[6, 7, 8, 9, 10]

上面代码逻辑很简单,就是将List集合里的前5个对象删除掉,然而结果却是相当不一样:第一个是错误的结果,第二个直接报异常,只有第三个是我们想要的结果!


那么这是为什么呢?其实主要原因来自于List中的remove()方法。我们来分析一下:

第一种方法:

第一次执行完remove方法后,并不像我们简单想象的那样就把第一个删除了,“1”这个对象被删除了没错,但是当被删除后List中“2”以后的9个对象的index索引也变了,都比原来的值减一,换句话说就是剩下的9个对象的index值为从0到8,而不是原来的从1到9了,那么第二次执行remove方法时,此时class="tags" href="/tags/LIST.html" title=list>list.remove(1)删除的就是“3”这个对象(“3”的index值为1),而不是我们想象的删除“2”对象。

第二种方法:

原因跟上面一样,导致List的next()方法内部出现modCount和expectedModCount不一致导致抛出异常。


所以我们这里建议大家采用第三种方法来删除List集合中某一个对象,这样做是最简单且容易记忆的。那第一种方法和第二种方法有没有解决的办法呢?目前我知道第一种方法的解决办法,第二种应该是无解的(因为语法结构导致)。


第一种方法的改进措施:

class="language-java">	void remove(List<Integer> class="tags" href="/tags/LIST.html" title=list>list) {
		int num = class="tags" href="/tags/LIST.html" title=list>list.size() - 5;
		for (int i = 0; i < num; i++) {
			class="tags" href="/tags/LIST.html" title=list>list.remove(i);
			i--;
			num--;
		}
	}


我想你编程时间长了,也会偶尔遇到这些类似简单却让你头疼的问题,遇到这些问题首先检查下自己的逻辑是否有问题,如果逻辑没有问题就检查下代码的结构是否有问题吧,这就是所谓的基本功,以后我也会慢慢的加强巩固自己基本功方面的能力,一起加油吧。


http://www.niftyadmin.cn/n/1661412.html

相关文章

Tomcat配置SSL安全协议

Tomcat配置SSL安全协议 文档说明&#xff1a;本文件适用于用JSSE设置Tomcat的SSL。 如果使用APR, Tomcat是通过 OpenSSL来实现SSL&#xff0c;设置会不同。 一、SSL简介 在网络上&#xff0c;信息在由源主机到目标主机的传输过程会经过其他计算机&#xff0c;网络上的信息有…

log4j.xml实例

tomcat/webapps/myProject/WEB-INF/log4j.xml: <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j"http://jakarta.apache.org/log4j/"…

http协议请求响应详解

http协议请求响应详解一、http协议简介 HTTP是HyperText TransferProtocol(超文本传输协议)的简写&#xff0c;它是TCP/IP协议的一个应用层协议&#xff0c;用于定义WEB浏览器与WEB服务器之间交换数据的过程及数据本身的格式。 二、HTTP1.0的基本运行方式 1、基于HTTP协议的…

Android网络编程(五):HTTP协议

一、简介 HTTP&#xff08;HyperText Transfer Protocol&#xff09;即超文本传输协议&#xff0c;我们前面TCP/IP协议章节讲过&#xff0c;HTTP协议属于TCP/IP协议族中的一员&#xff0c;TCP/IP协议族横跨OSI模型中的应用层、传输层、网络层和数据链路层&#xff0c;而HTTP协…

mongodb入门简介

一、基本概念 MongoDB 是一个高性能&#xff0c;开源&#xff0c;无模式的文档型数据库&#xff0c;是当前NoSQL 数据库产品中最热门的一种。它在许多场景下可用于替代传统的关系型数据库或键/值存储方式&#xff0c;MongoDB 使用C开发。MongoDB 的官方网站地址是&#xff1a;…

Android架构:MVVM实现离线登录

一、MVVM简介 MVVM模式是指Model-View-ViewModel。关于MVP架构&#xff0c;无论如何抽象化&#xff0c;在我们的View层中是无法避免的要处理一部分逻辑的。而MVVM模式中的View是将View的状态和行为完全抽象化&#xff0c;把逻辑与界面的控制完全交给ViewModel处理。 MVVM由下…

快速排序算法:小学生也能看就懂!

1、简介 快速排序&#xff08;Quicksort&#xff09;是对冒泡排序的一种改进&#xff0c;快速排序由C. A. R. Hoare在1960年提出。它的基本思想是&#xff1a;通过一趟排序将要排序的数据分割成独立的两部分&#xff0c;其中一部分的所有数据都比另外一部分的所有数据都要小&a…

mongodb数据库命令操作

上一节我们讲解了对于mongodb的一些认识和概念&#xff0c;那么接下来就要切实步入mongodb的学习中了。 mongodb不像关系型数据库有很强大的GUI客户端&#xff0c;虽然mongodb也有&#xff0c;但功能和稳定性实在不敢恭维&#xff0c;所以操作mongodb我们大部分都是用类似cmd命…