Stack Overflow上关于Java Collections的几个常见问题
下面列出Stack Overflow上最常见的几个关于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()方法,如下:
Iterator<Integer> it = list.iterator();
while(it.hasNext()){
// do something
it.remove();
}
一种最常见的错误代码如下:
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。
int[] array = ArrayUtils.toPrimitive(list.toArray(new Integer[0]));
在JDK中,没有捷径。需要注意的是,不能直接使用List.toArray(),因为这样会将List转化成Integer[]而不是int[]。正确的做法如下:
int[] array = new int[list.size()];
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呢?
还是得自己实现:
int[] array = {1,2,3,4,5};
List<Integer> list = new ArrayList<Integer>();
for(int i: array) {
list.add(i);
}
5. 过滤一个Collection最好的方法是什么?
如过滤掉list中大于5的整数。
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。
Set<Integer> set = new HashSet<Integer>(list);
Set<Integer> set = new TreeSet<Integer>(aComparator);
set.addAll(list);
7. 如何删除ArrayList中重复的元素?
如果不关心元素在ArrayList中的顺序,可以将list放入set中来删除重复元素,然后在放回list。
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构造器。
ArrayList<Integer> dstList = new ArrayList<Integer>(srcList);
另一种是使用Collections.copy()。
ArrayList<Integer> dstList = new ArrayList<Integer>(srcList.size());
Collections.copy(dstList, srcList);
需要注意的是,使用该方法的话目标list至少跟源list长度一样长。否则会报IndexOutOfBoundsException异常。
另外有两点需要注意:
- 两种方法都是浅拷贝
Collections.copy()方法的两个参数必须都是list,而ArrayList方法参数只要是collection即可,因此ArrayList方法更通用。

扫一扫关注公众号: FullStackPlan 获取更多干货哦~
Stack Overflow上关于Java Collections的几个常见问题的更多相关文章
- Stack Overflow 上 370万浏览量的一个问题:如何比较 Java 的字符串?
在逛 Stack Overflow 的时候,发现了一些访问量像喜马拉雅山一样高的问题,比如说这个:如何比较 Java 的字符串?访问量足足有 370万+,这不得了啊!说明有很多很多的程序员被这个问题困 ...
- [转帖]Stack Overflow上188万浏览量的提问:Java 到底是值传递还是引用传递?
Stack Overflow上188万浏览量的提问:Java 到底是值传递还是引用传递? http://www.itpub.net/2019/12/03/4567/ 在逛 Stack Overfl ...
- JavaScript超越了Java,c,python等等成为Stack Overflow上最热门的
JavaScript超越了Java,c,python等等成为Stack Overflow上最热门的标签 在2015年6月至今,JavaScript超越了Java,c,python等等成为Stack O ...
- Stack Overflow 上排名前十的与API相关的问题
Stack Overflow是一个庞大的编程知识仓库,在Stack Overflow 上,数百万的提问被回答,并且这些回答都是高质量的.这就是为什么在Google搜索结果的排行榜上,Stack Ove ...
- 为什么开发者热衷在Stack Overflow上查阅API文档?
摘要:一项新研究跟踪了Android开发者的访问历史,发现开发者多达二分之一的文档是从Stack Overflow上获取到的,而Stack Overflow上的示例也多于官方指南,开发者通过搜索更多时 ...
- Stack Overflow 上 250W 浏览量的一个问题:你对象丢了
在逛 Stack Overflow 的时候,发现最火的问题竟然是:什么是 NullPointerException(java.lang.NullPointerException),它是由什么原因导致的 ...
- Stack Overflow上59万浏览量的提问:为什么会发生ArrayIndexOutOfBoundsException?
在逛 Stack Overflow 的时候,发现了一些访问量像昆仑山一样高的问题,比如说这个:为什么会发生 ArrayIndexOutOfBoundsException?这样看似简单到不值得一问的问题 ...
- 关于Java Collections的几个常见问题
列举几个关于Java Collections的常见问题并给出答案. 1. 什么时候用LinkedList,什么时候用ArrayList? ArrayList是使用数组实现的list,本质上就是数组.A ...
- Stack Overflow 上人气最旺的 10 个 Java 问题
1. 为什么两个(1927年)时间相减得到一个奇怪的结果? (3623个赞) 如果执行下面的程序,程序解析两个间隔1秒的日期字符串并比较: public static void main(String ...
随机推荐
- HTML5新增核心工具——本地存储
除了Canvas元素外,HMTL5另外一个新增的非常重要的功能是可以在客户端本地存储数据库的Web Storage.本文就介绍下Web Storage以及SQLLite操作. Web Storage分 ...
- Linux之linux基础命令2
目录相关: 创建目录: mkdir 目录名 递归创建a/b c/d: mkdir -p a/b c/d 递归创建test/a,b,c,d四个目录: mkdir - p test{a,b,c,d} 递归 ...
- JUC——线程同步辅助工具类(Semaphore,CountDownLatch,CyclicBarrier)
锁的机制从整体的运行转态来讲核心就是:阻塞,解除阻塞,但是如果仅仅是这点功能,那么JUC并不能称为一个优秀的线程开发框架,然而是因为在juc里面提供了大量方便的同步工具辅助类. Semaphore信号 ...
- OpenGL学习笔记(1) 画一个三角形
最近找实习有一丢丢蛋疼,沉迷鬼泣5,四周目通关,又不想写代码,写篇笔记复习一下,要好好学图形学啊 用OpenGL画一个三角形 项目的简介 记录一下跟着learnOpenGL学习的过程 笔记里的代码放在 ...
- 使用yum安装文件时提示安装文件重复问题2:nodejs-10.15.3-1nodesource.x86_64: [Errno 256] No more mirrors to try.
原因:yum命令缓存问题 解决办法: sudo yum clean all
- Hadoop源码阅读环境搭建(IDEA)
拿到一份Hadoop源码之后,经常关注的两件事情就是 1.怎么阅读?涉及IDEA和Eclipse工程搭建.IDEA搭建,选择源码,逐步导入即可:Eclipse可以选择后台生成工程,也可以选择IDE导入 ...
- window搭建私有云,只要几分钟
本文介绍如何在window搭建私有云网盘. 工具/原料:一台window系统电脑或者window服务器(vps),Xampp 安装包,可道云kodexplorer安装包 第一步,xampp安装 1.官 ...
- docker node项目 连接mongodb
在弄docker部署node项目的时候遇到了连接mongdb的问题,记录一下问题解决办法 一.Docker 安装 MongoDB 1.查找Docker Hub上的mongo镜像 [root@VM_49 ...
- 企业上云这四大要点,你 get 了吗?
本文由 Platform9(一家专注于云计算.专有云.混合云.OpenStack 以及容器技术的北美初创公司)技术产品营销经理 Akshai Parthasarathy 撰写,描述了企业在向云基础设施 ...
- AssertionError
(1)p1 = multiprocessing.Process(test1)p2 = multiprocessing.Process(target=test2) 错误: p1缺少target,应为(t ...