下面列出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. Spring中的数据库事物管理

    Spring中的数据库事物管理 只要给方法加一个@Transactional注解就可以了 例如:

  2. 错误结果保存示例 - 【jmeter】

  3. MFC -- Excel操作简介(基于VS2010)

    一.添加与 Excel 操作相关的头文件 项目 -> 类向导,在右上方有一个下拉栏,选择其中的 类型库中的MFC类(T),即可看到下图所示界面,选择“文件”选项,然后在下方的位置选项中添加本地文 ...

  4. 微信小程序——音阶练耳 宣传页面

    音阶练耳是什么? 音阶练耳小程序是一款听音练习音阶,拥有简介界面的交互式小程序,以虚拟钢琴为辅助乐器,应用于日常练习,涵盖了五个八度内26种调式.以及下行中的所有调式与和声小调式的衍生,提高辨认音阶的 ...

  5. 2-Seventh Scrum Meeting20151207

    任务分配 闫昊: 今日完成:完成数据库设计. 明日任务:和唐彬讨论接口如何在android实现. 唐彬: 今日完成:读了IOS讨论区后台接口. 明日任务:和闫昊讨论接口如何在android实现. 史烨 ...

  6. 实验三:敏捷开发与XP实践

    Java实验三报告 一.   实验内容 (一)敏捷开发与XP 内容:1.敏捷开发(Agile Development)是一种以人为核心.迭代.循序渐进的开发方法. 2.极限编程(eXtreme Pro ...

  7. win10系统下载-靠谱推荐

    win10系统下载的靠谱推荐: 1.http://www.xitongtiandi.net/wenzhang/win10/12926.html 2.https://msdn.itellyou.cn/ ...

  8. 线程局部存储TLS(thread local storage)

    同一全局变量或者静态变量每个线程访问的是同一变量,多个线程同时访存同一全局变量或者静态变量时会导致冲突,尤其是多个线程同时需要修改这一变量时,通过TLS机制,为每一个使用该全局变量的线程都提供一个变量 ...

  9. Hibernate笔记③--集合映射、组合映射、联合主键、查询案例

    lazy 懒加载 默认为proxy   继承映射 discriminant column="type" type="string"   集合映射 生成表的语句: ...

  10. Codeforces Round #258 (Div. 2) 容斥+Lucas

    题目链接: http://codeforces.com/problemset/problem/451/E E. Devu and Flowers time limit per test4 second ...