这里主要谈下Java集合在使用中容易被忽略、又容易出现的两个“坑”,一个是集合与数组互相转换,另一个是集合遍历删除。主要通过代码演示。

  一.集合与数组互相转换中的“坑”  

//Test1.java
package com.itszt.test0419; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* 集合与数组互相转换,含list集合元素反序排列
*/
public class Test1 {
public static void main(String[] args) {
//一个集合对象
ArrayList<String> list=new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
//集合元素正反序转换
System.out.println("正序---list = " + list.toString());
Collections.reverse(list);
System.out.println("反序---list = " + list.toString());
Collections.reverse(list);
System.out.println("恢复初始状态---list"+list);
//(1)集合转数组
Object[] listArray1 = list.toArray();//方法1
System.out.println("方法1---listArray1 = " + Arrays.toString(listArray1));
String[] listArray2 = list.toArray(new String[list.size()]);//方法2
System.out.println("方法2---listArray2 = " + Arrays.toString(listArray2));
String[] listArray3=new String[list.size()];//方法3
for(int i=0;i<list.size();i++){
listArray3[i]=list.get(i);
}
System.out.println("方法3---listArray3 = " + Arrays.toString(listArray3));
//(2)数组转集合
List<Object> asList = Arrays.asList(listArray1);
/*
此时返回的ArrayList是Arrays的一个私有静态内部类,
可以遍历查询,但是不可以像普通集合那样增删元素
*/
System.out.println("asList = " + asList.toString());
/*
asList.add("f");
asList.remove("a");
//若增删元素,均会抛出异常 java.lang.UnsupportedOperationException
*/
//下述方法成功地将数组转化为集合
ArrayList arrayList = new ArrayList<>(asList);
arrayList.add("f");
arrayList.remove("a");
System.out.println("arrayList = " + arrayList.toString());
}
}

  二.集合遍历删除中的“坑”  

//Test2.java
package com.itszt.test0419;
import java.util.ArrayList;
import java.util.Iterator;
/**
* 集合遍历删除中的坑
* 推荐对JAVA集合进行遍历删除时用迭代器
*/
public class Test2 {
public static void main(String[] args) {
//一个集合对象
ArrayList<String> list=new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e"); //下面是错误的遍历删除方式,抛出异常:java.util.ConcurrentModificationException
/*for(String s:list){
list.remove(s);
}*/
//其实,上述代码在执行时,会转换成迭代器执行,但删除操作却用了错误的方法,如下所示:
/*for(Iterator<String> it=list.iterator();it.hasNext();){
String next = it.next();
list.remove(next);
}*/ //若将上述代码予以改写,就可以正常执行:
/*for(Iterator<String> it=list.iterator();it.hasNext();){
it.remove();
}
System.out.println("list = " + list.size());*/ /*
另外,下述方式不会报异常,但只能遍历删除部分元素。
这是因为:该方法中有一个严重的错误。
当一个元素被删除时,列表的大小缩小并且下标变化,
所以当你想要在一个循环中用下标删除多个元素的时候,它并不会正常生效。
*/
/*for(int i=0;i<list.size();i++){
list.remove(i);
}
System.out.println("list = " +
list.size()+"---"+
list.toString());*/ //下述方法可以清空集合内的所有元素
/*list.clear();
System.out.println("list = " +list.size());*/ //下述方式可以正确地删除指定内容的元素
/*for(int i=0;i<list.size();i++){
if("a".equals(list.get(i))){
list.remove(i);
}
}
System.out.println("list = " + list.toString());*/ /**
* 那么,为什么List集合使用迭代后,就不能再用集合自身的删除方法list.remove(i)了呢?
* 这是因为,ArrayList与Iterator混合使用时会导致各自的状态出现不一样,最终出现异常。
* ArrayList采用size属性来维护自已的状态,而Iterator采用cursor来来维护自已的状态。
* 当size出现变化时,cursor并不一定能够得到同步,除非这种变化是Iterator主动导致的。
* Iterator.remove方法导致ArrayList列表发生变化时,会自动更新cursor来同步这一变化。
* 但其他方式导致的ArrayList变化,Iterator是无法感知的。
* ArrayList不会主动通知Iterator,这将有损效率。
* 为了防止状态不一致可能引发的无法设想的后果,
* Iterator会经常做checkForComodification检查,以防有变。
* 如果有变,则以异常抛出,所以就抛出了上面的异常:
* java.util.ConcurrentModificationException
* 再来比较下面两种遍历删除方法:
*/ //错误的删除方法 抛出异常:java.util.ConcurrentModificationException
/*for(String s:list){
if("a".equals(s)){
list.remove(s);
}
}
System.out.println("list = " + list.toString());*/ //正确的删除方法
/*for(Iterator<String> it=list.iterator();it.hasNext();){
if("a".equals(it.next())){
it.remove();
}
}
System.out.println("list = " + list.toString());*/
/**
* 上述两种方法的不同结果是因为:
*.next()必须在.remove()之前调用。
* 在一个foreach循环中,编译器会使.next()在删除元素之后被调用,
* 因此就会抛出ConcurrentModificationException异常。
* 总之:
* Iterator 支持从源集合中安全地删除对象,
* 只需在 Iterator 上调用 remove() 即可。
* 这样做的好处是可以避免 ConcurrentModificationException ,
* 这个异常顾名思意:当打开 Iterator 迭代集合时,同时又在对集合进行修改。
* 为此,在对集合迭代时删除或添加元素时,调用 Iterator 的remove() 方法是个安全的做法。
*/
}
}

Java集合里的一些“坑”的更多相关文章

  1. Java集合源码学习(一)集合框架概览

    >>集合框架 Java集合框架包含了大部分Java开发中用到的数据结构,主要包括List列表.Set集合.Map映射.迭代器(Iterator.Enumeration).工具类(Array ...

  2. Java集合源码学习(一)Collection概览

    1.集合框架 Java集合框架包含了大部分Java开发中用到的数据结构,主要包括List列表.Set集合.Map映射.迭代器(Iterator.Enumeration).工具类(Arrays.Coll ...

  3. java 集合(Set1)

    ----------------|Collection(为什么要画这个图?学多了之后该忘了) --------------------------|List --------------------- ...

  4. 【原创】这道Java基础题真的有坑!我也没想到还有续集。

    前情回顾 自从我上次发了<这道Java基础题真的有坑!我求求你,认真思考后再回答.>这篇文章后.我通过这样的一个行文结构: 解析了小马哥出的这道题,让大家明白了这题的坑在哪里,这题背后隐藏 ...

  5. Java 集合看这一篇就够了

    大家好,这里是<齐姐聊数据结构>系列之大集合. 话不多说,直接上图: Java 集合,也称作容器,主要是由两大接口 (Interface) 派生出来的: Collection 和 Map ...

  6. Java集合【9】-- Vector源码解析

    目录 1.Vector介绍 2. 成员变量 3. 构造函数 4. 常用方法 4.1 增加 4.2 删除 4.3 修改 4.4 查询 4.5 其他常用函数 4.6 Lambda表达式相关的方法 4.7 ...

  7. java 集合 + 常见面试题

    1.1. 集合概述 1.1.1. Java 集合概览 从下图可以看出,在 Java 中除了以 Map 结尾的类之外, 其他类都实现了 Collection 接口. 并且,以 Map 结尾的类都实现了 ...

  8. 《面试补习》- Java集合知识梳理

    一.ArrayList ArrayList 底层数据结构为 动态数组 ,所以我们可以将之称为数组队列. ArrayList 的依赖关系: public class ArrayList<E> ...

  9. Java集合精选常见面试题

    前言 博主只是这篇文章的搬运工,为了加强记忆自己梳理了一遍并扩展了部分内容. 集合拓展链接:集合概述&集合之Collection接口 - 至安 - 博客园 (cnblogs.com) Java ...

随机推荐

  1. BZOJ1563/洛谷P1912 诗人小G 【四边形不等式优化dp】

    题目链接 洛谷P1912[原题,需输出方案] BZOJ1563[无SPJ,只需输出结果] 题解 四边形不等式 什么是四边形不等式? 一个定义域在整数上的函数\(val(i,j)\),满足对\(\for ...

  2. 70路小报:用PV和UV作为网站衡量指标已经过时

    方法]投资人呼吁:PV和UV不应该再作为产品衡量指标 风险投资机构Andreessen Horowitz近日一直反对再用传统的网站衡量指标去评价互联网产品,比如PV和UV,甚至包括应用的下载量. 他们 ...

  3. 【DP】【P5080】 Tweetuzki 爱序列

    Description Tweetuzki 有一个长度为 \(n\) 的序列 \(a_1~,~a_2~,~\dots~,a_n\). 他希望找出一个最大的 \(k\),满足在原序列中存在一些数 \(b ...

  4. 流媒体协议之RTSP客户端的实现20171014

    RtspClient是基于jrtplib实现的,目前仅支持h264格式,后续将不断迭代优化,加入对其他格式的支持,并且将实现RTSP的服务端. RtspClient的功能是接收服务端过来流,然后写入到 ...

  5. input 拍照上传

    <input id="up2" type="file" accept="image/*" capture="camera&q ...

  6. Stanford机器学习---第十四讲.机器学习应用举例之Photo OCR

    http://blog.csdn.net/l281865263/article/details/50278745 本栏目(Machine learning)包括单参数的线性回归.多参数的线性回归.Oc ...

  7. 关于GCD的几个结论

    设a和b的最大公约数是d,那么: 1. d是用sa+tb(s和t都是整数)能够表示的最小正整数 证明:设x=sa+tb是sa+tb能够表示出的最小正整数.首先,有d|x,证明如下: 因此有x>= ...

  8. dmsg命令使用

    http://note.youdao.com/noteshare?id=6771284da9f10ac35652907898d63141

  9. 手脱nSPack 2.2

    1.PEID查壳 深度扫描下:nSPack 2.2 -> North Star/Liu Xing Ping 2.载入OD,上来就是一个大跳转,F8单步跟下去 0040101B >- E9 ...

  10. .Net并行编程系列之一:并行基础

    现在普通PC平台上面多核处理器的普及,让我们领教了能够利用多核进行并行计算的软件的处理能力,同时继承更多地核心正是当前处理器发展的趋势. 但是作为一个.NET开发人员,是否有时候会发现你的程序占用了其 ...