关于Java Collections的几个常见问题
列举几个关于Java Collections的常见问题并给出答案。
1. 什么时候用LinkedList,什么时候用ArrayList?
ArrayList是使用数组实现的list,本质上就是数组。ArrayList中的元素可以通过索引随机获取一个元素。但是如果该数组已满,当添加新元素时需要分配一个新的数组然后将原来数组的元素移动过去,需要O(n)的时间复杂度。添加或删除一个元素需要移动数组中的其他元素。这是ArrayList最大的缺点。
LinkedList是一个双向链表。因此,当需要获取list中某个元素,需要从头到尾遍历list。另一方面,在链表中添加或删除元素很快,只需要O(1)的时间复杂度。从空间上来说,在链表中一个节点需要两个额外的指针来指向它的previous和next节点。
总结:
从时间复杂度来说,如果对list增加或删除操作较多,优先用LinkedList;如果查询操作较多,优先用ArrayList。
从空间复杂度来说,LinkedList会占用较多空间。
2. 如何边遍历边移除Collection中的元素
边遍历边修改Collection的唯一正确方式是使用Iterator.remove()方法,如下:
|
1
2
3
4
5
|
Iterator<Integer> it = list.iterator();while(it.hasNext()){ // do something it.remove();} |
一种最常见的错误代码如下:
|
1
2
3
|
for(Integer i : list){ list.remove(i)} |
运行以上错误代码会报ConcurrentModificationException异常。这是因为当使用foreach(for(Integer i : list))语句时,会自动生成一个iterator来遍历该list,但同时该list正在被Iterator.remove()修改。在Java中,一般不允许一个线程在遍历collection时另一个线程在修改它。
3. 如何将List转化成int[]?
很多人可能认为只需用List.toArray()即可,其实不然。List.toArray()方法只可能得到Integer[],无法得到int[]。
最简单的方法是使用Apache Commons Lang库中的ArrayUtils。
|
1
|
int[] array = ArrayUtils.toPrimitive(list.toArray(new Integer[0])); |
在JDK中,没有捷径。需要注意的是,不能直接使用List.toArray(),因为这样会将List转化成Integer[]而不是int[]。正确的做法如下:
|
1
2
3
4
|
int[] array = new int<div class="list "></div>;for(int i = 0; i < list.size(); i++){ array[i] = list.get(i);} |
4. 如何将int[]转化成List?
同上,很多人以为只需用Arrays.asList()即可,其实不然。因为不能以int[]作为该方法的参数,要的话也只能是Integer[]。
关于Arrays.asList()方法有如下特性:
- 1.该方法对于基本数据类型的数组支持并不好,当数组是基本数据类型时不建议使用
- 2.当使用asList()方法时,数组就和列表链接在一起了。当更新其中之一时,另一个将自动获得更新。因为asList获得的List实际引用的就是数组 注意:仅仅针对对象数组类型,基本数据类型数组不具备该特性。
- 3.asList得到的数组是的没有add和remove方法的。因为asList返回的List是Arrays中的内部类,而该类并没有定义add和remove方法。
那么如何将int[]转化成List呢?
还是得自己实现:
|
1
2
3
4
5
|
int[] array = {1,2,3,4,5};List<Integer> list = new ArrayList<Integer>();for(int i: array) { list.add(i);} |
5. 过滤一个Collection最好的方法是什么?
如过滤掉list中大于5的整数。
|
1
2
3
4
5
6
7
|
Iterator<Integer> it = list.iterator();while(it.hasNext()){ int i = it.next(); if(i > 5) { //过滤掉大于5的整数 it.remove(); }} |
6. 将List转化成Set最简单的方法?
有两种方法,取决于你怎么要怎么定义两个元素相等。第一种方法是将list放入HashSet里,该方法元素是否相等是通过它们的hashCode()来比较的。如果需要自己定义比较的方法,需要用TreeSet。
|
1
|
Set<Integer> set = new HashSet<Integer>(list); |
|
1
2
|
Set<Integer> set = new TreeSet<Integer>(aComparator);set.addAll(list); |
7. 如何删除ArrayList中重复的元素?
如果不关心元素在ArrayList中的顺序,可以将list放入set中来删除重复元素,然后在放回list。
|
1
2
3
|
Set<Integer> set = new HashSet<Integer>(list);list.clear();list.addAll(set); |
如果关心元素在ArrayList中的顺序,可以用LinkedHashSet。
8. 有序的collection
Java里有很多方法来维持一个collection有序。有的需要实现Comparable接口,有的需要自己指定Comparator。
Collections.sort()可以用来对list排序。该排序是稳定的,并且可以保证nlog(n)的性能。PriorityQueue提供排序的队列。PriorityQueue和Collections.sort()的区别是,PriorityQueue动态维护一个有序的队列(每添加或删除一个元素就会重新排序),但是只能获队列中的头元素。- 如果collection中没有重复的元素,
TreeSet是另一个选择。跟PriorityQueue一样的是,TreeSet也动态维护一个有序的集合。可以从TreeSet中获取最大和最小的元素。
总结:Collections.sort()提供一个一次排序的list。PriorityQueue和TreeSet动态维护排序的collection。
9. 拷贝list
有两种方法可以用来拷贝list。一种是使用ArrayList构造器。
|
1
|
ArrayList<Integer> dstList = new ArrayList<Integer>(srcList); |
另一种是使用Collections.copy()。
|
1
2
|
ArrayList<Integer> dstList = new ArrayList<Integer>(srcList.size());Collections.copy(dstList, srcList); |
需要注意的是,使用该方法的话目标list至少跟源list长度一样长。否则会报IndexOutOfBoundsException异常。
另外有两点需要注意:
- 两种方法都是浅拷贝
Collections.copy()方法的两个参数必须都是list,而ArrayList方法参数只要是collection即可,因此ArrayList方法更通用.
关于Java Collections的几个常见问题的更多相关文章
- Stack Overflow上关于Java Collections的几个常见问题
下面列出Stack Overflow上最常见的几个关于Java Collections的问题并给出答案. 1. 什么时候用LinkedList,什么时候用ArrayList? ArrayList是使用 ...
- Java编程最差实践常见问题详细说明(2)转
Java编程最差实践常见问题详细说明(2)转 2012-12-13 13:57:20| 分类: JAVA | 标签:java |举报|字号 订阅 反射使用不当 错误的写法: Java代 ...
- Java Collections Source Code Series 2 ---接口
废话开篇 自己学完Java Collections框架之后,其中的一个较大的收获就是接口对于层次的重要性.Java Collections的最终实现至少有几十个,其中很多都有非常相似的功能(metho ...
- Java Collections Source Code Series 1 --- 简介
废话开篇 由于项目需要,需要对Java Collections进行系统地了解,所以在此记录下,方便自己,服务他人. Java Collections 简介 Java Collections 框架主要包 ...
- 关于Java Collections API您不知道的5件事,第2部分
注意可变对象 java.util 中的 Collections 类旨在通过取代数组提高 Java 性能.如您在 第 1 部分 中了解到的,它们也是多变的,能够以各种方 式定制和扩展,帮助实现优质.简洁 ...
- 关于 Java Collections API 您不知道的 5 件事,第 1 部分
定制和扩展 Java Collections Java™ Collections API 远不止是数组的替代品,虽然一开始这样用也不错.Ted Neward 提供了关于用 Collections 做更 ...
- 关于 Java Collections API 您不知道的 5 件事--转
第 1 部分 http://www.ibm.com/developerworks/cn/java/j-5things2.html 对于很多 Java 开发人员来说,Java Collections A ...
- (一)一起学 Java Collections Framework 源码之 概述
. . . . . 目录 (一)一起学 Java Collections Framework 源码之 概述 JDK 中很多类 LZ 已经使用了无数次,但认认真真从源码级研究过其原理的还只占少数,虽然从 ...
- (二)一起学 Java Collections Framework 源码之 AbstractCollection
. . . . . 目录 (一)一起学 Java Collections Framework 源码之 概述(未完成) (二)一起学 Java Collections Framework 源码之 Abs ...
随机推荐
- 解决pl/sql 查询数据中文显示成?
解决方法: 1.打开 PLSQL Developer 安装目录下,看到有PLSQLDev.exe的目录, 在PLSQL Developer文件夹内新建“PLSql_run.bat”文件,在该文件中输入 ...
- 代理(Proxy)模式简介
一.代理(Proxy)模式简介 代理模式是结构型模式. 代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 代理对象要继承于抽象主题,并控制原对象的引用 二.简单例子 抽象主题类 ...
- redission 分布式锁
https://my.oschina.net/haogrgr/blog/469439 分布式锁和Redisson实现 Aug 20, 2017 CONTENTS 概述 分布式锁特性 Redis实现 ...
- 深入浅出搜索架构引擎、方案与细节 倒排 bitmap
深入浅出搜索架构引擎.方案与细节(上) 2017-02-14 23:55 58沈剑0 20 阅读 131 一.缘起 <100亿数据1万属性数据架构设计>文章发布后,不少朋友对58同城自 ...
- WINDOWS操作系统中可以允许最大的线程数
默认情况下,一个线程的栈要预留1M的内存空间 而一个进程中可用的内存空间只有2G,所以理论上一个进程中最多可以开2048个线程 但是内存当然不可能完全拿来作线程的栈,所以实际数目要比这个值要小. ...
- VC++程序员如何做好界面
本屌丝在新春放假期间闲来无事,在各大编程论坛溜达了一圈.发现年前的帖子中,有VC++程序员在界面开发方面遇到了很多苦恼,有抱怨界面工作不好做的,有抱怨用错了界面库的,也有紧急求得技术问题帮助的.看到这 ...
- 【自创+转发】jQuery给input 密码框绑定回车事件
<script type="text/javascript" src="Scripts/jquery-1.6.2.js"></script&g ...
- 更安全的HTTPS
iOS9把所有的http请求都改为https了:iOS9系统发送的网络请求将统一使用TLS 1.2 SSL.采用TLS 1.2 协议,目的是 强制增强数据访问安全,而且 系统 Foundation 框 ...
- Android开发之探秘蓝牙隐藏API
这次讲得深入些,探讨下蓝牙方面的隐藏API.用过Android系统设置(Setting)的人都知道蓝牙搜索之后可以建立配对和解除配对,但是这两项功能的函数没有在SDK中给出,那么如何去使用这两项功能呢 ...
- [iOS]过渡动画之高级模仿 airbnb
注意:我为过渡动画写了两篇文章:第一篇:[iOS]过渡动画之简单模仿系统,主要分析系统简单的动画实现原理,以及讲解坐标系.绝对坐标系.相对坐标系,坐标系转换等知识,为第二篇储备理论基础.最后实现 Ma ...