下面列出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。

  1. Collections.sort()可以用来对list排序。该排序是稳定的,并且可以保证nlog(n)的性能。
  2. PriorityQueue提供排序的队列。PriorityQueueCollections.sort()的区别是,PriorityQueue动态维护一个有序的队列(每添加或删除一个元素就会重新排序),但是只能获队列中的头元素。
  3. 如果collection中没有重复的元素,TreeSet是另一个选择。跟PriorityQueue一样的是,TreeSet也动态维护一个有序的集合。可以从TreeSet中获取最大和最小的元素。

总结:Collections.sort()提供一个一次排序的list。PriorityQueueTreeSet动态维护排序的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异常。

另外有两点需要注意:

  1. 两种方法都是浅拷贝
  2. Collections.copy()方法的两个参数必须都是list,而ArrayList方法参数只要是collection即可,因此ArrayList方法更通用。



扫一扫关注公众号: FullStackPlan 获取更多干货哦~

Stack Overflow上关于Java Collections的几个常见问题的更多相关文章

  1. Stack Overflow 上 370万浏览量的一个问题:如何比较 Java 的字符串?

    在逛 Stack Overflow 的时候,发现了一些访问量像喜马拉雅山一样高的问题,比如说这个:如何比较 Java 的字符串?访问量足足有 370万+,这不得了啊!说明有很多很多的程序员被这个问题困 ...

  2. [转帖]Stack Overflow上188万浏览量的提问:Java 到底是值传递还是引用传递?

    Stack Overflow上188万浏览量的提问:Java 到底是值传递还是引用传递? http://www.itpub.net/2019/12/03/4567/   在逛 Stack Overfl ...

  3. JavaScript超越了Java,c,python等等成为Stack Overflow上最热门的

    JavaScript超越了Java,c,python等等成为Stack Overflow上最热门的标签 在2015年6月至今,JavaScript超越了Java,c,python等等成为Stack O ...

  4. Stack Overflow 上排名前十的与API相关的问题

    Stack Overflow是一个庞大的编程知识仓库,在Stack Overflow 上,数百万的提问被回答,并且这些回答都是高质量的.这就是为什么在Google搜索结果的排行榜上,Stack Ove ...

  5. 为什么开发者热衷在Stack Overflow上查阅API文档?

    摘要:一项新研究跟踪了Android开发者的访问历史,发现开发者多达二分之一的文档是从Stack Overflow上获取到的,而Stack Overflow上的示例也多于官方指南,开发者通过搜索更多时 ...

  6. Stack Overflow 上 250W 浏览量的一个问题:你对象丢了

    在逛 Stack Overflow 的时候,发现最火的问题竟然是:什么是 NullPointerException(java.lang.NullPointerException),它是由什么原因导致的 ...

  7. Stack Overflow上59万浏览量的提问:为什么会发生ArrayIndexOutOfBoundsException?

    在逛 Stack Overflow 的时候,发现了一些访问量像昆仑山一样高的问题,比如说这个:为什么会发生 ArrayIndexOutOfBoundsException?这样看似简单到不值得一问的问题 ...

  8. 关于Java Collections的几个常见问题

    列举几个关于Java Collections的常见问题并给出答案. 1. 什么时候用LinkedList,什么时候用ArrayList? ArrayList是使用数组实现的list,本质上就是数组.A ...

  9. Stack Overflow 上人气最旺的 10 个 Java 问题

    1. 为什么两个(1927年)时间相减得到一个奇怪的结果? (3623个赞) 如果执行下面的程序,程序解析两个间隔1秒的日期字符串并比较: public static void main(String ...

随机推荐

  1. Unity学习笔记(4): 碰撞相关API

    Unity3D中的碰撞: 在unity中,有普通碰撞体Collider和触发器(Trigger)两种碰撞体,两个普通碰撞体会发生碰撞并产生力学现象,触发器则像是个无法触碰而又真实存在的东西,也会触发碰 ...

  2. 004 --Mysql中的锁的问题

    死锁 死锁是指两个或多个事务在同一个资源上相互占用, 并请求锁定对方占用的资源, 从而导致恶性循环的现象. 当多个事务试图以不同顺序锁定资源时, 就可能产生死锁.死锁发生以后, 只有部分或者完全回滚其 ...

  3. [文章存档]Azure .net WebAPP的js/css文件过大导致访问慢的解决办法

    https://docs.azure.cn/zh-cn/articles/azure-operations-guide/app-service-web/aog-app-service-web-qa-j ...

  4. 从零开始的Python学习Episode 17——序列化

    序列化 我们把对象(变量)从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语 言中也被称之为serialization,marshalling,flattenin ...

  5. linux压缩相关

    tar命令 tar是打包,即把好多东西放在一个大文件里面,之后再压缩:当然也可以解包 tar的几个参数说明: -c 创建一个新的包 -x 将包里的文件还原出来 -t 显示包内文件的列表 -f 指定要处 ...

  6. [机器学习]-K近邻-最简单的入门实战例子

    本篇文章分为两个部分,前一部分主要简单介绍K近邻,后一部分是一个例子 第一部分--K近邻简介 从字面意思就可以容易看出,所谓的K近邻,就是找到某个样本距离(这里的距离可以是欧式距离,曼哈顿距离,切比雪 ...

  7. Scrum立会报告+燃尽图(十二月九日总第四十次):视频剪辑与用户反馈

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2484 项目地址:https://git.coding.net/zhang ...

  8. Windows下Visual Studio2017之AI环境搭建

    本博客主要包含以下3点: AI简介及本博客主要目的 环境介绍及安装原因 搭建环境及检验是否安装成功 离线模型的训练 时间分配:   时间 时长(分钟) 收集资料+写博客 6.12 11:28-12:2 ...

  9. Scrum Meeting 5 -2014.11.11

    放假过掉一大半.大家都努力赶着进度,算法实现基本完成.可能还有些细小的改动,但也可以统一进入测试阶段了. 今天叫了部分在校人员开了个小会.任务决定以测试为主,同时开始进行服务器的部署. 在之前尝试服务 ...

  10. 针对网站的UI分析

    PM对项目所有功能的把握,特别是UI 最差的UI,体现了团队的组织架构.其次,体现了产品的内部结构.最好,体现了用户的自然需求. 对于几种浏览器分别进行UI分析, (1)360的界面如今看来比较大众化 ...