关于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。

  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构造器。

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异常。

另外有两点需要注意:

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

转载于:https://www.cnblogs.com/baizhanshi/p/6482923.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/429590.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32 USB虚拟串口原理(上)

USB虚拟串口是使用USB的CDC&#xff08;CDC为communication device class(virtual port com)&#xff09;类实现的一种通讯接口。使用STM32自带的USB slave功能可以在电脑上实现一个USB虚拟串口&#xff0c;在电脑上可以直接使用串口调试助手打开该虚拟串口和STM32进行通讯。ST…

RT-Thread使用ENV生成工程时自己添加的文件被清掉的解决方法

在项目中难得一次就可以将需要的模块或组件包添加完成&#xff0c;因此在实际开发中经常会遇到在未完成的项目中增加软件包或使能硬件功能的情况。一般我们会使用RT-Thread的ENV辅助开发环境的menuconfig图形化系统配置工具对组件包进行配置&#xff0c;配置完后使用pkgs --upd…

怎样使用两行代码实现博客园打赏功能

也许大家看博客园博客的时候&#xff0c;遇到过一些博客右侧&#xff0c;展示了打赏二维码~ 如下图所示 那么&#xff0c;这是怎么实现的呢~~~ 不错&#xff0c;你没猜错&#xff0c;他们使用的是本人写的一个js插件--tctip。 大家搜一下&#xff0c;还能搜到网上有些tctip的教…

STM32 HAL库 .c/.h 文件介绍

HAL库中各个文件的介绍&#xff1a; startup_stm32l475xx.s 启动文件的主要作用是进行RAM中堆、栈内存的分配和初始化&#xff0c;中断向量表及中断函数的定义等&#xff0c;进行完这一系列工作后执行系统复位从而跳转至用户main函数开始执行。 stm32l4xx_hal_ppp.c/.h 基本…

【bzoj3514】 Codechef MARCH14 GERALD07加强版

http://www.lydsy.com/JudgeOnline/problem.php?id3514 (题目链接) 题意 给出$n$个点$m$条边的无向图&#xff0c;询问保留图中编号在$[l,r]$的边的时候图中的连通块的个数。 Solution 将边的编号作为权值用LCT维护一个最大生成树&#xff0c;同时记录一下加入当前边$i$会把哪…

C语言中将浮点数四舍五入取整的宏定义(支持正数和负数的圆整)

在实际工程项目中经常会需要将浮点型的计算结果四舍五入为整型&#xff0c;因此定义如下宏定义对浮点型进行圆整。若所需圆整的浮点型结果正负号无法确定&#xff0c;则需要将结果圆整为带符号的整型结果如int8_t、int16_t、int32_t等。对于结果>0的浮点数和<0的浮点数圆…

原码、反码、补码,计算机中所有的数都是以补码的形式存储的

计算机中所有的数都是以补码的形式存储的 原码&#xff1a; 一个数的原码就是其10进制的数转换为2进制数&#xff0c;正数的原码符号位为0&#xff0c;负数的原码符号位为1。 如10进制的数26667&#xff0c;将其转换为2进制为0110 1000 0010 1011。10进制的数-26667&#xf…

RT-Thread设备框架学习感悟

前面几周跟着野火的教程从0到1实现了RT-Thread的内核&#xff0c;对RT-Thread的调度机制和线程、定时器的底层实现有了总体的了解。后面还需进一步对齐实现细节进行探索&#xff0c;但大致先了解其框架&#xff0c;后面再进行细致的了解。在学习新知识时&#xff0c;最重要的是…

Tensorflow之RNN,LSTM

Tensorflow之RNN,LSTM #!/usr/bin/env python2 # -*- coding: utf-8 -*- """ tensorflow之RNN 循环神经网络做手写数据集分类 """import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data#设置随机数来比较两种计算…

python selenium T3

python selenium T3 既然要做自动,就得对得起自动化的这个名字。这一章我们将进一步的增加自动化测试的实用,增加自动发邮件功能、多线程 和定时任务,让我们的自动化工作真正变得高效而又强大起来。 EG1 : with open(report.html , r) as f:msg MIMEText(f.read() , _subtypeh…

RT-Thread中自定义MSH命令传入的参数是字符串,需用户自行检查和解析

如下是在将安富莱的dac8563模块对接到潘多拉开发板RT-Thread SPI设备框架中时导出到RT-Thread的自定义MSH命令&#xff0c;需要注意的是MSH传入的是字符串&#xff0c;需要自行对字符串进行解析处理。 #include "stdlib.h" /* 使用其中的函数&#xff1a;atoi(); */…

水平+垂直布局-css (借鉴)

1. 水平居中 方法一&#xff1a;margin:0 auto; &#xff08;最常用的居中布局方式&#xff09;方法二&#xff1a;text-align和inline-block的结合&#xff08;设置父元素的text-align为center&#xff09;。 这种方式最好应用于图片、按钮、文字之类的居中模式&#xff0c;否…

安富莱DAC8653模块

产品规格&#xff1a;1、供电电压 &#xff1a; 2.7 - 5.5V 【3.3V供电时&#xff0c;输出电压也可以到正负10V】2、通道数&#xff1a; 2路 &#xff08;通过1片DAC8563实现&#xff09;3、输出电压范围 &#xff1a; -10V ~ 10V 【客户可以自己更改为 0-10V输出范围。使…

AD16 SCH原理图打开正常,PCB图纸打开为空白或仍是上一个界面的解决方法

重新安装AD16并激活后&#xff0c;发现SCH图纸打开正常&#xff0c;但打开PCB图纸时要么显示一片空白&#xff0c;要么显示的还是上一屏的内容&#xff0c;重启AD16软件或者重启电脑都没有用。 【问题原因】电脑显卡驱动有问题 【解决方法】更新或重新安装电脑显卡驱动 step…

flex布局应用与踩坑

一、预告本文不是一篇入门的文章所有请符合以下条件的战斗人员绕道&#xff1a; 1、初学前端&#xff0c;对前端的传统布局还不是很熟悉的人 2、后端人员对前端不打算深入学习的同学 二、开篇flex布局原本是好几个月前就一直想学习的东西&#xff0c;当时flex布局还算是比较新鲜…

RT-Thread I/O设备模型

I/O设备指的是嵌入式系统中的一些Input输入/Output输出设备&#xff0c;输入输出设备是嵌入式系统重要的组成部分。输入和输出设备可以看做是计算机系统和外界进行沟通的桥梁&#xff0c;因此在计算机组成原理中输入输出设备是重要的组成部分。 计算机组成原理中的5大组成部分…

如何使用易我数据恢复向导恢复数码相机删除的图片

1 使用"易我数据恢复向导"的高级恢复(务必将数码相机的存储卡取出单独插入SD卡槽,而不是直接用数据线连接到电脑上,这样存储卡才能以磁盘方式显示) 2 选中对应磁盘,点击下一步 3 如果出现"分区参数不正确"提示&#xff0c;直接取消即可开始搜索 4 搜索完…

RT-Thread对GPIO操作两种方式的区别:1)通过设备操作接口2)直接通过通用GPIO设备驱动

在学习RT-Thread设备驱动框架时&#xff0c;看到潘多拉开发板的RT-Thread例程资料中的文档《AN0002-RT-Thread-通用 GPIO 设备应用笔记》有如下描述&#xff0c;因此产生使用文档中未使用的方式1&#xff09;通过设备操作接口 方法实现GPIO操作的想法&#xff01; 使用潘多拉开…

英语----情态动词(下)

should 应该 竟然 Youd should go to school right now. I should help him. How should i know. Im surprised tha he that he should be so rude to you. it worries me its a pity. You cant imagine.... ought to // 用在比较严肃的场合 You ought to take car…

清华大学-曾鸣-《ARM微控制器与嵌入式系统》I2C总线(一)

I2C是一种双向2线制同步串行通讯接口&#xff0c;是一类非常经典的串行总线通讯&#xff0c;理解好I2C通讯会帮助理解USB通讯、以太网通讯中的握手、数据帧等环节。 I2C的发展历史&#xff1a; SPI串行通讯主要是由MOTOROLA公司提出的&#xff0c;MOTOROLA公司的半导体部门独立…