Java常用的一些容器

转自:https://www.cnblogs.com/LipeiNet/p/5888513.html

前言:在java开发中我们肯定会大量的使用集合,在这里我将总结常见的集合类,每个集合类的优点和缺点,以便我们能更好的使用集合。下面我用一幅图来表示

其中淡绿色的表示接口,红色的表示我们经常使用的类。

1:基本概念

Java容器类类库的用途是保存对象,可以将其分为2个概念。

1.1:Collection

一个独立元素的序列,这些元素都服从一条或多条规则。其中List必须按照插入的顺序保存元素、Set不能有重复的元素、Queue按照排队规则来确定对象的产生顺序(通常也是和插入顺序相同)

1.2:Map

一组成对的值键对对象,允许用键来查找值。ArrayList允许我们用数字来查找值,它是将数字和对象联系在一起。而Map允许我们使用一个对象来查找某个对象,它也被称为关联数组。或者叫做字典。

2:List

List承诺可以将元素维护在特定的序列中。List接口在Collection的基础上加入了大量的方法,使得可以在List中间可以插入和移除元素。下面主要介绍2种List

2.1:基本的ArrayList

它的优点在于随机访问元素快,但是在中间插入和移除比较慢

那么现在我们就一起来看看为什么ArrayList随机访问快,而插入移除比较慢。先说关于ArrayList的初始化。

ArrayList有三种方式进行初始化如下

复制代码
private transient Object[] elementData;
public ArrayList() {this(10);}public ArrayList(int initialCapacity) {super();if (initialCapacity < 0)throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);this.elementData = new Object[initialCapacity];}public ArrayList(Collection<? extends E> c) {elementData = c.toArray();size = elementData.length;// c.toArray might (incorrectly) not return Object[] (see 6260652)if (elementData.getClass() != Object[].class)elementData = Arrays.copyOf(elementData, size, Object[].class);}
复制代码

我们可以看出ArrayList其实就是采用的是数组(默认是长度为10的数组)。所有ArrayList在读取的时候是具有和数组一样的效率,它的时间复杂度为1。

插入尾部就是elementData[size++] = e;当然中间会进行扩容。现在主要说插入中间为什么相对来说比较慢源码如下

复制代码
 public void add(int index, E element) {rangeCheckForAdd(index);//验证(可以不考虑)ensureCapacityInternal(size + 1);  // Increments modCount!!(超过当前数组长度进行扩容)System.arraycopy(elementData, index, elementData, index + 1,size - index);(核心代码)elementData[index] = element;size++;}
复制代码

System.arraycopy(elementData, index, elementData, index + 1)第一个参数是源数组,源数组起始位置,目标数组,目标数组起始位置,复制数组元素数目。那么这个意思就是从index索性处每个元素向后移动一位,最后把索引为index空出来,并将element赋值给它。这样一来我们并不知道要插入哪个位置,所以会进行匹配那么它的时间赋值度就为n。

2.2:LinkedList

它是通过代价较低在List中间进行插入和移除,提供了优化的顺序访问,但是在随机访问方面相对较慢。但是他的特性功能要比ArrayList强大的多。支持Queue和Stack

ListedList采用的是链式存储。链式存储就会定一个节点Node。包括三部分前驱节点、后继节点以及data值。所以存储存储的时候他的物理地址不一定是连续的。

我们看下它的中间插入实现

从代码我们可以看出先获取插入索引元素的前驱节点,然后把这个元素作为后继节点,然后在创建新的节点,而新的节点前驱节点和获取前驱节点相同,而后继节点则等于要移动的这个元素。所以这里是不需要循环的,从而在插入和删除的时候效率比较高。

我们在来看看查询(我们可以分析出它的效率要比ArrayList低了不少)

3:Set

Set也是一个集合,但是他的特点是不可以有重复的对象,所以Set最常用的就是测试归属性,很容易的询问出某个对象是否存在Set中。并且Set是具有和Collection完全一样的接口,没有额外的功能,只是表现的行为不同。

3.1:HashSet

HashSet查询速度比较快,但是存储的元素是随机的并没有排序,下面我写一段程序看一下

复制代码
public static void main(String[] args){/*** 没有顺序可循,这是因为hashset采用的是散列(处于速度考虑)*/Random random=new Random(47);Set<Integer> intset=new HashSet<Integer>();for (int i=0;i<10000;i++){intset.add(random.nextInt(30));}System.out.print(intset);}
复制代码

3.2:TreeSet

TreeSet是将元素存储红-黑树结构中,所以存储的结果是有顺序的(所以如果你想要自己存储的集合有顺序那么选择TreeSet)

复制代码
public static void main(String[] args){Random random=new Random(47);Set<Integer> intset=new TreeSet<Integer>();for (int i=0;i<10000;i++){intset.add(random.nextInt(30));}System.out.print(intset);}
复制代码

 关于LinkedHashSet后面再说。

4:Queue

Queue是队列,队列是典型的先进先出的容器,就是从容器的一端放入元素,从另一端取出,并且元素放入容器的顺序和取出的顺序是相同的。LinkedList提供了对Queue的实现,LinkedList向上转型为Queue。其中Queue有offer、peek、element、pool、remove等方法

offer是将元素插入队尾,返回false表示添加失败。peek和element都将在不移除的情况下返回对头,但是peek在对头为null的时候返回null,而element会抛出NoSuchElementException异常。poll和remove方法将移除并返回对头,但是poll在队列为null,而remove会抛出NoSuchElementException异常,以下是例子

复制代码
  public static void main(String[] args){Queue<Integer> queue=new LinkedList<Integer>();Random rand=new Random();for (int i=0;i<10;i++){queue.offer(rand.nextInt(i+10));}printQ(queue);Queue<Character> qc=new LinkedList<Character>();for (char c:"HelloWorld".toCharArray()){qc.offer(c);}System.out.println(qc.peek());printQ(qc);List<String> mystrings=new LinkedList<String>();mystrings.add("1");mystrings.get(0);Set<String> a=new HashSet<String>();Set<String> set=new HashSet<String>();set.add("1");}public static void printQ(Queue queue){while (queue.peek
复制代码

从上面的输出的结果我们可以看出结果并不是一个顺序的,没有规则的,这个时候如果想让队列按照规则输出那么这个时候我们就要考虑优先级了,这个时候我们就应该使用PriorityQueue,这个时候如果在调用offer方法插入一个对象的时候,这个对象就会按照优先级在对列中进行排序,默认的情况是自然排序,当然我们可以通过Comparator来修改这个顺序(在下一篇讲解)。PriorityQueue可以确保当你调用peek、pool、remove方法时,获取的元素将是对列中优先级最高的元素。ok我们再次通过代码查看

复制代码
 public static void main(String[] args) {PriorityQueue<Integer> priorityQueue = new PriorityQueue<Integer>();Random rand = new Random();for (int i = 0; i < 10; i++) {priorityQueue.offer(rand.nextInt(i + 10));}QueueDemo.printQ(priorityQueue);List<Integer>ints= Arrays.asList(25,22,20,18,14,9,3,1,1,2,3,9,14,18,21,23,25);priorityQueue=new PriorityQueue<Integer>(ints);QueueDemo.printQ(priorityQueue);}
复制代码

从输出可以看到,重复是允许的,最小值拥有最高优先级(如果是String,空格也可以算作值,并且比字母具有更高的优先级)如果你想消除重复,可以采用Set进行存储,然后把Set作为priorityQueue对象的初始值即可。

5:Map

Map在实际开发中使用非常广,特别是HashMap,想象一下我们要保存一个对象中某些元素的值,如果我们在创建一个对象显得有点麻烦,这个时候我们就可以用上map了,HashMap采用是散列函数所以查询的效率是比较高的,如果我们需要一个有序的我们就可以考虑使用TreeMap。这里主要介绍一下HashMap的方法,大家注意HashMap的键可以是null,而且键值不可以重复,如果重复了以后就会对第一个进行键值进行覆盖。

put进行添加值键对,containsKey验证主要是否存在、containsValue验证值是否存在、keySet获取所有的键集合、values获取所有值集合、entrySet获取键值对。

复制代码
 public static void main(String[] args){//Map<String,String> pets=new HashMap<String, String>();Map<String,String> pets=new TreeMap<String, String>();pets.put("1","张三");pets.put("2","李四");pets.put("3","王五");if (pets.containsKey("1")){System.out.println("已存在键1");}if (pets.containsValue("张三")){System.out.println("已存在值张三");}Set<String> sets=pets.keySet();Set<Map.Entry<String , String>> entrySet= pets.entrySet();Collection<String> values=  pets.values();for (String value:values){System.out.println(value+";");}for (String key:sets){System.out.print(key+";");}for (Map.Entry entry:entrySet){System.out.println("键:"+entry.getKey());System.out.println("值:"+entry.getValue());}}
复制代码

6:Iterator和Foreach

现在foreach语法主要作用于数组,但是他也可以应用于所有的Collection对象。Collection之所以能够使用foreach是由于继承了Iterator这个接口。下面我写段代码供大家查看

复制代码
public class IteratorClass {public Iterator<String> iterator(){return new Itr();}private class Itr implements Iterator<String>{protected String[] words=("Hello Java").split(" ");private int index=0;public boolean hasNext() {return index<words.length;}public String next() {return words[index++];}public void remove() {}}
}
复制代码
复制代码
 Iterator iterators=new IteratorClass().iterator();for (Iterator it=iterator;iterators.hasNext();) {System.out.println(iterators.next());}while (iterators.hasNext()){System.out.println(iterators.next());}
复制代码

从中我们可以看出foreach循环最终是转换成 for (Iterator it=iterator;iterators.hasNext();)只不过jdk帮我们隐藏我们无法查看。下面我们在来分析一个问题,关于List删除问题。我们大多肯定使用过for循环或者foreach循环去删除,但是结果很明显会出现错误,那么现在我们一起分析为啥会出现错误。

1:使用for循环删除(出现错误分析)

2:foreach循环删除(错误分析)

从上面我们得知foreach最终是会转成Iterator的所以它首先会通过next来获取元素,我们看代码

 请看for循环删除那段代码,没删除一次modCount会++,所以第二次在次删除的时候modCount由于增加和expectedModCount不等所以无法获取元素也就无法删除。

3:正确的删除方式

采用迭代器代码如下

 Iterator<String> iterator=userList.iterator();while (iterator.hasNext()){iterator.next();iterator.remove();}

请记住一定要加上iterator.next();这是因为在源码中有一个lastRed,通过它来记录是否是最后一个元素,如果不加上iterator.next()那么lastRed=-1,在删除验证的时候有这么一段代码if (lastRet < 0)throw new IllegalStateException();所以就会抛出异常。

 

7:Collections和Arrays

这里只介绍2个常用的Collections.addAll和Arrays.asList

addAll:

asList采用的是数组

可以看出最终转换成ArrayList。

 8:总结

1):数组是将数字和对象联系起来,它保存明确的对象,查询对象时候不需要对查询结果进行转换,它可以是多维的,可以保存基本类型的数据,但是数组一旦生成,其容量不能改变。所以数组是不可以直接删除和添加元素。

2):Collection保存单一的元素,而Map保存相关联的值键对,有了Java泛型,可以指定容器存放对象类型,不会将错误类型的对象放在容器中,取元素时候也不需要转型。而且Collection和Map都可以自动调整其尺寸。容器不可以持有基本类型。

3):像数组一样,List也建立数字索性和对象的关联,因此,数组和List都是排好序的容器,List可以自动扩容

4):如果需要大量的随机访问就要使用ArrayList,如果要经常从中间插入和删除就要使用LinkedList。

5):各种Queue和Stack由LinkedList支持

6):Map是一种将对象(而非数字)与对象相关联的设计。HashMap用于快速访问,TreeMap保持键始终处于排序状态,所以不如HashMap快,而LinkedHashMap保持元素插入的顺序,但是也通过散列提供了快速访问的能力

7):Set不接受重复的元素,HashSet提供最快的访问能力,TreeSet保持元素排序状态,LinkedHashSet以插入顺序保存元素。

转载于:https://www.cnblogs.com/jkzr/p/10729124.html

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

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

相关文章

图灵奖得主杨立昆:AI+时代,未来将会如何被改变

来源&#xff1a;杨立昆《科学之路&#xff1a;人&#xff0c;机器与未来》编辑&#xff1a;蒲蒲人工智能&#xff08;AI&#xff09;近年来的发展可以说包罗万象&#xff0c;几乎涵盖了所有与机器智能化相关的内容。无论是机器人、冰箱、汽车还是软件应用&#xff0c;只要你想…

基于IMAGE法的房间回响模型创建、C++代码实现、matlab仿真

基于IMAGE法的房间回响模型创建、C代码实现、matlab仿真1.模型简介 \qquad在处理声音信号时&#xff0c;我们要对信号先进行采集。那么我们就必须要有&#xff0c;一个发出声音的声源&#xff0c;一个进行声音采集的传感器。并且这两者一般都位于房间之中&#xff0c;处于房间内…

花落有机化学!诺贝尔化学奖不再是“理综奖”

来源&#xff1a;学术头条北京时间 2021 年 10 月 6 日下午 5 点 50 分&#xff0c;2021 年诺贝尔化学奖重磅公布&#xff0c;德国马普煤炭研究所所长 Benjamin List、普林斯顿大学化学教授 David W.C. MacMillan 获奖&#xff0c;以表彰他们对“不对称有机催化做出的贡献”。关…

牛客 16499 解方程 (数学、Python)

同个人网站 https://www.serendipper-x.cn/&#xff0c;欢迎访问 &#xff01; 链接&#xff1a;https://ac.nowcoder.com/acm/problem/16499 来源&#xff1a;牛客网 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 131072K&#xff0c;其他语…

美军认知技术发展态势

来源&#xff1a;人机与认知实验室摘要&#xff1a;美军正在大力发展人工智能中的认知技术&#xff0c;认知技术的进步将极大的促进人机融合智能的发展。首先&#xff0c;综述了美军认知技术的发展历史&#xff0c;从自然语言处理、环境感知、机器人自主控制、自主编组协调、人…

正则表达式写验证器

package com.office.utility;import java.util.regex.Pattern;/*** 校验器&#xff1a;利用正则表达式校验用户名、密码、邮箱、手机号等* author liujiduo*/ public class Validator {/*** 正则表达式&#xff1a;验证用户名*/public static final String REGEX_USERNAME &qu…

【操作系统复习】中断和异常

同个人网站 https://www.serendipper-x.cn/&#xff0c;欢迎访问 &#xff01; 中断和异常一、中断机制的诞生二、中断的概念和作用三、中断的分类四、外中断的处理过程一、中断机制的诞生 &#x1f481; 早期的计算机&#xff1a;各程序只能串行执行&#xff0c;系统资源利用…

东南亚的招聘骗局,程序员请注意!

阅读本文大概需要 5.2 分钟。 总有些我认为是常识的事情&#xff0c;在别人看来都是第一次接触。很多骗局都是如此&#xff0c;圈内人不上当&#xff0c;圈外人不警惕。毕竟骗子吃的就是信息不对称的生意。关于东南亚的招聘骗局&#xff0c;便是如此。 他们当前主力针对的是程序…

2021年深度学习哪些方向比较有研究潜力?

来源&#xff1a;知乎问答作者&#xff1a;陀飞轮、Zhifeng、谢凌曦转自&#xff1a;极市平台深度学习成为近些年来较为热门的领域&#xff0c;算法工程师这一岗位也变得越发的抢手&#xff0c;尽管已经踏入了这一领域但对整体的大环境其实是还不能够准确的把握。从研究方向去看…

视觉感知与认知

2. 视觉感知与认知 2. 视觉感知与认知2.1 感知与认知2.1.1 视觉感知处理过程2.1.2 格式塔理论2.1.2.1 贴近法则 (proximity)2.1.2.2 相似法则 (similarity)2.1.2.3 连续原则 (continuity)2.1.2.4 闭合原则 (closure)2.1.2.5 共势原则 (common fate)2.1.2.6 好图原则 (good figu…

高文:拥抱人工智能

转自&#xff1a;《中国信息化周报》2020年40期本文根据中国工程院院士高文公开演讲整理而成&#xff0c;未经本人确认高文&#xff0c;中国工程院院士什么叫人工智能呢&#xff1f;人工智能是人类智能的一个计算机的实现&#xff0c;从对决的角度&#xff0c;它永远不可能超过…

3.6数对 (Python)

链接&#xff1a;https://ac.nowcoder.com/acm/contest/12478/C 来源&#xff1a;牛客网 时间限制&#xff1a;C/C 2秒&#xff0c;其他语言4秒 空间限制&#xff1a;C/C 262144K&#xff0c;其他语言524288K 64bit IO Format: %lld 题目描述 在3月6日&#xff0c;作为队内数…

互联网大脑的发育与元宇宙的兴起

2021年10月2日&#xff0c;《互联网大脑的发育与元宇宙的兴起》是远望智库数字大脑研究院院长刘锋博士受奇点O论坛的邀请所做的一个发言&#xff0c;从互联网大脑模型的发育角度&#xff0c;探讨了元宇宙兴起的原因和规律&#xff0c;同时对元宇宙面临的问题和对产业的影响进行…

小凡做蛋糕(Python)

链接&#xff1a;https://ac.nowcoder.com/acm/contest/12478/G 来源&#xff1a;牛客网 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 65536K&#xff0c;其他语言131072K 64bit IO Format: %lld 一开始把整个二维数组填好了&#xff0c;然后…

对于使用progisp软件进行ISP编程时进入不了编程模式的解决方法

目录 对于使用progisp软件进行ISP编程时无法进入编程模式的解决方法前提说明Win10 解决方法Win10 "禁用强制驱动程序签名"Win10 手动安装驱动。Win7解决方法Win7 "禁用强制驱动程序签名"Win7 手动安装驱动说明标题: 对于使用progisp软件进行ISP编程时无法进…

陈杰院士:多无人系统协同中的人工智能安全探索

来源&#xff1a;中国工程院院刊作者&#xff1a;施文、王楷文、俞成浦、孙健、陈杰&#xff0c;控制理论与控制工程专家、中国工程院院士。多无人系统协同作为一项人工智能的颠覆性技术&#xff0c;将在空间上分布的无人系统有机连接起来&#xff0c;在给社会创造价值的过程中…

圆的交点 (Python)

链接&#xff1a;https://ac.nowcoder.com/acm/contest/12478/D 来源&#xff1a;牛客网 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 262144K&#xff0c;其他语言524288K 64bit IO Format: %lld 2&#xff0c;1的样例 一层一层找规律…

linux的常用操作——基于ftp的windows10和腾讯云centos操作系统之间的文件上传和下载

\qquad在腾讯云服务器的centos操作系统上&#xff0c;安装vsftpd并进行配置&#xff0c;然后基于ftp实现windows10操作系统和腾讯云centos系统之间的文件上传和下载。 文章目录1.基于腾讯云服务器centos的操作系统的vsftpd的安装和配置2.基于ftp实现windows10和linux之间的文件…

这些超级高效的人工神经元不使用电子?

Nanofluidic slits in this artificial neuron prototype mimic the ion channels in the brain. PAUL ROBIN/LABORATOIRE DE PHYSIQUE DE LENS来源&#xff1a;IEEE电气电子工程师在能源使用和信息传输能力方面&#xff0c;设计模仿人脑的电子系统是科学研究的圣杯。尽管人工…

工具资源系列之给虚拟机装个windows

前面我们介绍了如何在 mac 宿主机安装 VMware 虚拟机软件,本节我们将继续介绍如何给虚拟机安装镜像,切换不同的操作系统. VMware 软件是容器,镜像是内核,这里的镜像指的是操作系统. 下载镜像 windows 操作系统下载: https://msdn.itellyou.cn/ 按照实际需要选择适合自己的操作系…