Java集合(Collection List Set Map)

news2024/9/20 22:54:12

文章目录

    • Collection接口和常用方法
        • Collection接口遍历元素方式1 -使用Iterator(迭代器)
        • Collection接口遍历对象方式2-for循环增强
    • List接口和常用方法
        • List[ArrayList, LinkedList, Vector]的三种遍历方式
        • ArrayList的注意事项
        • ArrayList的底层操作机制源码分析
        • Vector和ArrayList的比较
        • LinkedList底层结构
        • LinkedList的底层操作机制
        • ArrayList和LinkedList的比较
    • Set接口和常用方法
        • HashSet的全面说明
        • HashSet底层机制说明
        • HashSet的扩容和转成红黑树机制
        • Set接口实现类 - LinkedHashSet
    • Map接口和常用方法
        • 常用方法
        • Map遍历方式
        • HashMap小结
        • HashMap底层机制
        • Map接口实现类 -HashTable的基本介绍
        • Map接口实现类 - Properties基本介绍
    • 总结-开发中如何选择集合实现类
    • Collections工具类

image-20221201231214042

集合的理解和好处

前面我们保存多个数据使用的是数组,那么数组有不足的地方,我们分析一下。

1)长度开始时必须指定,而且一旦指定,不能更改
2)保存的必须为同一类型的元素
3)使用数组进行增加元素的示意代码-比较麻烦

那么集合有哪些好处呢?

1)可以动态保存任意多个对象,使用比较方便!
2)提供了一系列方便的操作对象的方法: add、 remove、 set、 get等
3)使用集合添加, 删除新元素的示意代码-简洁了

Collection接口和常用方法

public interface Collection<E> extends Iterable<E>

1)collection实现子类可以存放多个元素,每个元素可以是Object
2)有些Collection的实现类,可以存放重复的元素,有些不可以
3)有些Collection的实现类,有些是有序的(List),有些不是有序(Set)
4)Collection接口没有直接的实现子类,是通过它的子接口Set和List来实现的

Collection接口常用方法,以实现子类ArrayList来演示

  1. add:添加单个元素
  2. remove:删除指定元素
  3. contains:查找元素是否存在
  4. size:获取元素个数
  5. isEmpty:判断是否为空
  6. clear:清空
  7. addAll:添加多个元素
  8. containsAll:查找多个元素是否都存在
  9. removeAll:删除多个元素

Collection接口遍历元素方式1 -使用Iterator(迭代器)

  1. Iterator对象称为迭代器,主要用于遍历Collection集合中的元素。
  2. 所有实现了Collection接口的集合类都有一个iterator(方法, 用以返回一个实现 了Iterator接口的对象,即可以返回一个迭代器。
  3. Iterator的结构
  4. Iterator仅用于遍历集合,Iterator 本身并不存放对象。

image-20221202151134809

import java.util.ArrayList;
import java.util.Iterator;

public class Collection01 {
    public static void main(String[] args) {
        ArrayList al = new ArrayList();
        al.add("AA");
        al.add(11);
        al.add("三国演义");
        Iterator iterator = al.iterator();
        while (iterator.hasNext()) {
            Object obj = iterator.next();
            System.out.println(obj);
        }
    }
}

Collection接口遍历对象方式2-for循环增强

增强for循环,可以代替iterator迭代器, 特点: 增强for就是简化版的iterator, 本质一样。只能用于遍历集合或数组。

基本语法

for(元素类型 元素名:集合名或数组名) {
	访问元素
}

List接口和常用方法

List接口是Collection接口的子接口

  1. List集合类中元素有序(即添加顺序和取出顺序一 致)、 且可重复
  2. List集合中的每个元素都有其对应的顺序索引,即支持索引。
  3. List容器中的元素都对应一 个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素

List集合里添加了一些根据索引来操作集合元素的方法

  1. void add(int index, Object ele):在index位置插入ele元素
  2. boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来
  3. Object get(int index):获取指定index位置的元素
  4. int indexOf(Object obj):返回obj在集合中首次出现的位置
  5. int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置
  6. Object remove(int index):移除指定index位置的元素,并返回此元素
  7. Object set(int index, Object ele):设置指定index位置的元素为ele , 相当于是替换
  8. List subList(int fromIndex, int tolndex): 返回从fromIndex到tolndex位置的子集合

List[ArrayList, LinkedList, Vector]的三种遍历方式

方式一:使用iterator

方式二:使用增强for

方式三:使用普通for

ArrayList的注意事项

  1. permits all elements, includling null , ArrayList可以加入nulI,并且多个
  2. ArrayList是由数组来实现数据存储的
  3. ArrayList基本等同于Vector ,除了ArrayList是线程不安全(执行效率高)看源码.
    在多线程情况下,不建议使用ArrayList

ArrayList的底层操作机制源码分析

  1. ArrayList中维护了-个Object类型的数组elementData. [debug 看源码]
    transient Object[] elementData;
  2. 当创建对象时,如果使用的是无参构造器,则初始elementData容量为0 (jdk7是10)
  3. 当添加元素时:先判断是否需要扩容,如果需要扩容,则调用grow方法,否则直接添加元素到合适位置
  4. 如果使用的是无参构造器,如果第一次添加, 需要扩容的话,则扩容elementData为10,
    如果需要再次扩容的话,则扩容elementData为1.5倍。
  5. 如果使用的是指定容量capacity的构造器,则初始elementData容量为capacity
  6. 如果使用的是指定容量capacity的构造器,如果需要打容,则直接扩容elementData为 1.5倍。

Vector和ArrayList的比较

image-20221202175147853

LinkedList底层结构

  1. LinkedList底层实现了双向链表和双端队列特点
  2. 可以添加任意元素(元素可以重复),包括null
  3. 线程不安全,没有实现同步

LinkedList的底层操作机制

  1. LinkedList底层维护了一个双向链表.
  2. LinkedList中维护了两个属性first和last分别指向首节点和尾节点
  3. 每个节点(Node对象) ,里面又维护了prev、next、 item三个属性, 其中通过
    prev指向前一个,通过next指向后一个节点。最终实现双向链表
  4. 所以LinkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高
  5. 模拟一个简单的双向链表走代码

image-20221202203528475

ArrayList和LinkedList的比较

这俩都是线程不安全的

image-20221202212347845

如何选择ArrayList和LinkedList:
1)如果我们改查的操作多,选择ArrayList
2)如果我们增删的操作多,选择LinkedList
3)一般来说,在程序中,80%-90%都是查询,因此大部分情况下会选择ArrayList
4)在一个项目中,根据业务灵活选择,也可能这样,一个模块使用的是ArrayList,另外一个模块是LinkedList.

Set接口和常用方法

1 无序(添加和取出的顺序不一致),没有索引
2 不允许重复元素,所以最多包含一个null
3 JDK APl中Set接口的实现类有: AbstractSet, ConcurrentSkipListSet, CopyOnWriteArraySet, EnumSet, HashSet, JobStateReasons, LinkedHashSet, TreeSet

和List接口一样,Set接口也是Collection的子接口,因此,常用方法和Collection接口一样.

同Collection的遍历方式一样,因为Set接口是Collection接口的子接口。
1.可以使用迭代器
2.增强for
3.不能使用索引的方式来获取元素.

HashSet的全面说明

  1. HashSet实现了Set接口
  2. HashSet实际上是HashMap,看下源码.
  3. 可以存放null值,但是只能有一个null
  4. HashSet不保证元素是有序的,取决于hash后,再确定索引的结果.
  5. 不能有重复元素/对象.在前面Set接口使用已经讲过

HashSet底层机制说明

分析HashSet的添加元素底层是如何实现(hash() + equals())

image-20221203114644214

  1. HashSet 底层是HashMap
  2. 添加一个元素时,先得到hash值-会转成->索引值
  3. 找到存储数据表table ,看这个索引位置是否已经存放的有元素
  4. 如果没有,直接加入
  5. 如果有,调用equals比较,如果相同,就放弃添加,如果不相同,则添加到最后
  6. 在Java8中,如果条链表的元素个数超过TREEIFY THRESHOLD(默认是8),并且table的大小 >=MIN_ TREEIFY CAPACITY(默认64),就会进行树化(红黑树)

HashSet的扩容和转成红黑树机制

  1. HashSet底层是HashMap,第一次添加时,table 数组扩容到16,临界值(threshold)是 16 ∗ 加 载 因 子 ( l o a d F a c t o r ) 是 0.75 = 12 16*加载因子(loadFactor)是0.75 = 12 16(loadFactor)0.75=12
  2. 如 果table数组使用到了临界值12,就会扩容到16* 2 = 32,新的临界值就是32*0.75 = 24,依次类推
  3. 在Java8中,如果一条链表的元素个数到达TREEIFY THRESHOLD(默认是8 ),并且table的大小>=MIN TREEIFY CAPACITY(默认64),就会进行树化(红黑树),否则仍然采用数组扩容机制

Set接口实现类 - LinkedHashSet

  1. LinkedHashSet是HashSet的子类
  2. LinkedHashSet底层是一个LinkedHashMap,底层维护了一个数组+双向链表
  3. LinkedHashSet根据元素的hashCode值来决定元素的存储位置,同时使用链表维护元素的次序(图),这使得元素看起来是以插入顺序保存的。
  4. LinkedHashSet不允许添重复元素

image-20221203153346871

Map接口和常用方法

注意:这里讲的是JDK8的Map接口特点 Map_ java

  1. Map与Collection并列存在。用于保存具有映射关系的数据:Key-Value
  2. Map中的key和value可以是任何引用类型的数据,会封装到HashMap$Node对象中
  3. Map中的key不允许重复,原因和HashSet一样,前面分析过源码.
  4. Map中的value可以重复
  5. Map的key可以为null, value也可以为null,注意key为null,只能有一个,value为null ,可以多个.
  6. 常用String类作为Map的key
  7. key和value之间存在单向一对一关系,即通过指定的key总能找到对应的value
  8. Map存放数据的key-value示意图,-对k-v是放在一 个Node中的,有因为Node实现了Entry接口,有些书上也说一对k-v就是一个Entry(如图)

image-20221203164207865

常用方法

  1. put:添加
  2. remove:根据键删除映射关系
  3. get:根据键获取值
  4. size:获取元素个数
  5. isEmpty:判断个数是否为0
  6. clear:清除
  7. containsKey:查找键是否存在

Map遍历方式

1)containsKey:查找键是否存在
2)keySet:获取所有的键
3)entrySet:获取所有关系k-v
4)values:获取所有的值

image-20221203172045700

image-20221203172604821

image-20221203172806391

HashMap小结

  1. Map接口的常用实现类: HashMap、 HashTable和Properties。
  2. HashMap是Map接口使用频率最高的实现类。
  3. HashMap是以key-val对的方式来存储数据(HashMap$Node)
  4. key不能重复,但是是值可以重复,允许使用null键和null值。
  5. 如果添加相同的key,则会覆盖原来的key-val ,等同于修改.(key不会替换,val会替换)
  6. 与HashSet一样,不保证映射的顺序,因为底层是以hash表的方式来存储的.
  7. HashMap没有实现同步,因此是线程不安全的

HashMap底层机制

  1. HashMap底层维护了Node类型的数组table,默认为null
  2. 当创建对象时,将加载因子(loadfactor)初始化为0.75.
  3. 当添加key-val时,通过key的哈希值得到在table的索引。然后判断该索引处是否有元素,如果没有元素直接添加。如果该索引处有元素,继续判断该元素的key是否和准备加入的key相等,如果相等,则直接替换val;如果不相等需要判断是树结构还是链表结构,做出相应处理。如果添加时发现容量不够,则需要扩容。
  4. 第1次添加,则需要扩容table容量为16,临界值(threshold)为12.
  5. 以后再扩容,则需要扩容table容量为原来的2倍,临界值为原来的2倍,即24,依次类推
  6. 在Java8中,如果一条链表的元素个数超过TREEIFY THRESHOLD(默认是8),并且table的大小>= MIN TREEIFY CAPACITY(默认64),就会进行树化(红黑树)

Map接口实现类 -HashTable的基本介绍

  1. 存放的元素是键值对:即K-V
  2. hashtable的键和值都不能为null,否则会抛出NullPointerException
  3. hashTable使用方法基本上和HashMap-样
  4. hashTable是线程安全的,hashMap 是线程不安全的
  5. 简单看下底层结构

Map接口实现类 - Properties基本介绍

  1. Properties类继承自Hashtable类并且实现了Map接口, 也是使用一种键值对的形式来保存数据。
  2. 他的使用特点和Hashtable类似
  3. Properties 还可以用于从xxx.properties文件中,加载数据到Properties类对象,并进行读取和修改
  4. 说明: 工作后xx.properties 文件通常作为配置文件,这个知识点在I0流举例,有兴趣可先看文章

总结-开发中如何选择集合实现类

1)先判断存储的类型(一组对象[单列]或一组键值对[双列])
2)一组对象[单列]: Collection接口
允许重复: List
增删多: LinkedList [底层维护了一个双向链表]
改查多: ArrayList [底层维护Object类型的可变数组]
不允许重复: Set
无序: HashSet [底层是HashMap ,维护了一个哈希表即(数组+链表红黑树)]
排序: TreeSet
插入和取出顺序一致: LinkedHashSet , 维护数组+双向链表
3)一组键值对:Map
键无序: HashMap [底层是:哈希表jdk7: 数组+链表,jdk8:数组+链表+红黑树]
键排序: TreeMap
键插入和取出顺序一致: LinkedHashMap
读取文件Properties

Collections工具类

  1. Object max(Collection): 根据元素的自然顺序,返回给定集合中的最大元素
  2. Object max(Collection, Comparator): 根据Comparator指定的顺序,返回给定集合中的最大元素
  3. Object min(Collection)
  4. Object min(Collection, Comparator)
  5. int frequency(Collection, Object): 返回指定集合中指定元素的出现次数
  6. void copy(List dest,List src):将src中的内容复制到dest中
    ections工具类

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

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

相关文章

【已解决】vue后台页面跳转无法正常显示

今天写后端&#xff0c;发现一个问题&#xff0c;我的其他页面之间都可以正常跳转显示&#xff0c;但是我的其中一个页面&#xff08;简称U页面&#xff09;&#xff0c;我跳转到U页面时还可以显示&#xff0c;但之后点击其他页面就无法正常显示了&#xff08;能跳转不能显示&a…

chapter6——流水线的艺术

目录1.影响最大时钟频率的因素2.流水线3.DLX指令集的实现4.流水线对吞吐率的影响5.流水线原理6.流水线冒险结构冒险数据冒险控制冒险其他冒险对高速ASIC日益增长的需求使得越来越需要增加电路每个时钟周期的计算吞吐率。可以通过流水线提高ASIC在这方面的性能&#xff0c;但是也…

首个大规模图文多模态数据集LAION-400M介绍

前言 openAI的图文多模态模型CLIP证明了图文多模态在多个领域都具有着巨大潜力&#xff0c;随之而来掀起了一股图文对比学习的风潮。 就在前几天&#xff08;2022年12月&#xff09;&#xff0c;连Kaiming都入手这一领域&#xff0c;将MAE的思路与CLIP的思路结合&#xff0c;…

MySQL常用高级语句

SQL高级语句 DISTINCT 不显示重复的内容 语法&#xff1a;SELECT DISTINCT “字段” FROM “表名”; select distinct name from lk1;SELECT 显示表格中一个或数个栏位的所有资料 语法&#xff1a;SELECT “字段” FROM “表名”; select * from lk1; #查看表格详细信息…

微机原理与汇编语言—理论知识复习

书上重点内容 本篇博客整理老师课上强调的重点理论知识&#xff0c;以便复习备考&#xff0c;如有错误欢迎指正。 这门课主要讲CPU芯片与其他芯片&#xff08;内存芯片和I/O接口芯片&#xff09;之间交互。 一条指令的执行过程&#xff1a;取指&#xff08;从主存取到CPU寄…

最优化理论笔记及期末复习(《数值最优化》——高立)

目录一、预备知识二、无约束最优化方法的基本结构三、凸集和凸函数四、负梯度方法和Newton型方法五、共轭梯度法六、约束最优化问题的最优性理论七、罚函数方法八、期末复习8.1 知识点复习8.2 习题复习8.3 大实验代码8.3.1实验内容8.3.2实验目的8.3.3算法描述8.3.4程序中的参数…

[附源码]计算机毕业设计基于Springboot的中点游戏分享网站

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【C++】STL:String

&#x1f431;作者&#xff1a;傻响 &#x1f431;专栏&#xff1a;《C/C - STL》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; ​ 目录 STD - String标准库 字符串类介绍 字符串类构造函数 No.1 string() ; No.2 string(const char…

实操1 : Jupyter Notebook 如何更换主题+全部主题展示+深色主题下如何设置可视化图表

文章目录(一) 如何更换主题(二) 全部主题展示(三) 深色主题下设置可视化图表(一) 如何更换主题 1.打开 Jupyter Notebook, 新建一个Python文件 在文件中输入下方命令开始安装主题 pip install --upgrade jupyterthemes -i https://pipy.douban.com/simple2.win R 打开 cmd 命…

效率工具之Arthas

Arthas 阿里巴巴开源的Java诊断工具&#xff1b;追踪方法执行链、反编译、监控JVM状态 在线安装 使用 1. trace 跟踪调用链 解决痛点&#xff1a;定位问题根据日志推理分析&#xff0c;方法出入参不可见&#xff0c;分支判断太多情况下 定位很慢&#xff0c;分析出可能有问…

[附源码]JAVA毕业设计科院垃圾分类系统(系统+LW)

[附源码]JAVA毕业设计科院垃圾分类系统&#xff08;系统LW&#xff09; 目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术…

JVM学习-- JVM调优

一、选择垃圾收集器 垃圾收集器和内存大小有关 一般情况&#xff0c; serialserial old 适用几十兆内存 pspo 适用几百兆~几个G parNewCMS 可以用到20G G1 可以用到上百G ZGC 可以 4T~16T 1. 常见垃圾收集器组合参数设定 -XX:UseConc(urrent)MarkSweepGC ParNew CM…

【web实战-业务逻辑】评论点赞逻辑

目录 点赞逻辑一&#xff1a; 第一步&#xff1a;找关键 第二步&#xff1a;猜测逻辑 第三步&#xff1a;结论 第四步&#xff1a;归类 点赞逻辑二&#xff1a; 第一步&#xff1a;找关键 第二步&#xff1a;猜测逻辑 第三步&#xff1a;结论 第四步&#xff1a;归纳…

Framework 学习之旅:Service 启动过程

前言 Service 的启动过程将分为两个部分&#xff0c;分别是ContextImpl到ActivityManageService调用过程和ActivityThread启动Service过程。 ContextImpl到ActivityManageService调用过程 一般启动服务操作在Activity中调用startService方法&#xff0c;从Activity的startSe…

[附源码]计算机毕业设计springboot智慧园区运营管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

360T7路由器进行WiFi无线中继教程

360T7路由器进行WiFi中继教程1. 概述2. 360T7路由器进行WiFi中继实现教程2.1 登录路由器管理界面2.2 选择上网方式2.3 搜索WiFi2.4 连接WiFi2.5 点击确认2.6 在主页面查看网络1. 概述 中继路由系统由一组中继路由器组成&#xff0c;为不能交换路由信息的路由域提供中继路由。该…

关于小程序session_key漏洞问题的解决2022-12-01

业务背景&#xff1a;开发了小程序&#xff0c;使用了一段时间以后&#xff0c;小程序提示系统漏洞session_key的问题&#xff0c;在网上找了好多的博客&#xff0c;感觉好多写的没那么清晰&#xff0c;更偏重于理论&#xff0c;导致自己走了很多的弯路&#xff0c;为了更方便快…

基于海鸥算法优化的lssvm回归预测-附代码

基于海鸥算法优化的lssvm回归预测 - 附代码 文章目录基于海鸥算法优化的lssvm回归预测 - 附代码1.数据集2.lssvm模型3.基于海鸥算法优化的LSSVM4.测试结果5.Matlab代码摘要&#xff1a;为了提高最小二乘支持向量机&#xff08;lssvm&#xff09;的回归预测准确率&#xff0c;对…

【树莓派不吃灰】Linux服务器篇(核心概念)

目录1. 第一章 架设服务器前的准备工作2. 第二章 基础网络概念3. 第三章 局域网络架构简介4. 第四章 连上 Internet5. 第五章 Linux 常用网络指令6. 第六章 Linux 网络侦错7. 第七章 网络安全与主机基本防护8. 第八章 路由观念与路由器设定9. 第九章 防火墙与 NAT 服务器&#…

Python源码剖析2-字符串对象PyStringObject

二、 1、PyStringObject与 PyString_Type PyStringObject是变长对象中的不可变对象。当创建了一个PyStringObject对象之后,该对象内部维护的字符串就不能再被改变了。这一点特性使得 PyStringObject 对象能作为 PyDictObject 的键值,但同时也使得一些字符串操作的效率大大降低…