Java入门-java的集合框架

集合概念

集合,有时也称作容器(Container), 是对象的持有者,它们可以有助于高效访问的方式存储的组织对象。以生活中的案例为例: 集合就像装衣服的柜子,衣服就是集合中的元素。

img

集合框架图

image-20240527172334115

Collection中每次操作的都是一个对象,如果要操作一对对象就必须使用Map,Map中所有的对象都按照key->value形式保存,也称二元偶对象。Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法。Collections 类是 Java 提供的一个操作 Set、List 和 Map 等集合的工具类。

泛型

泛型概念

把类型明确的工作推迟到创建对象或调用方法的时候才去明确的特殊的类型。

泛型一般表示为<E>

例如:

public class ArrayList<E> implements List<E>{}

这个ArrayList类中用到的类,用E替代(泛型), 当创建对象时才明确它的类型。

new ArrayList<String>(); //创建对象时泛型明确为String类型

为什么使用泛型?

  • 使代码更加简洁

  • 使程序更加健壮

  • 提高可读性和稳定性

程序案例:

List<User> users = new ArrayList<>();
User user = new User();
users.add(user); 

如程序演示:使用泛型定义了对象使用类型为Dog类型,如果使用其它类型编译器检查则会报错,早检查出错增强程序的健壮性。

泛型的擦除

java的一个特性,在运行时,java不会保留泛型。

Java 泛型的参数只可以代表类,不能代表个别对象。由于Java泛型的类型参数之实际类型在编译时会被消除,所以无法在运行时得知其类型参数的类型。Java 编译器在编译泛型时会自动加入类型转换的编码,故运行速度不会因为使用泛型而加快。

泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单。

泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,以提高代码的重用率。

通配符泛型

无边界通配符: 例如List<?> , ? 表示不确定的java类型。

固定上边界通配符: 例如List<? extends Car> ,表示指定类的子类,Car即为上边界。

固定下边界通配符: 例如List<? super Car>,表示Car的父类,Car即为下边界。

Collection接口

The root interface in the collection hierarchy。

集合层次结构的根接口。定义了集合的常用api。

image-20240527172736069

List接口

List接口是Collection接口的子接口。有序的集合,存储元素和取出元素的顺序是一致的(存储abc则取出abc)有索引,包含了一些带索引的方法允许存储重复的元素。

ArrayList

ArrayList类特性

底层由动态数组构成,即数组的长度可变。

ArrayList的类层次结构

image-20240526175020435

image-20240526175048180

image-20240526175107499

ArrayList的属性

数组的初始长度为10

private static final int DEFAULT_CAPACITY = 10;private static final Object[] EMPTY_ELEMENTDATA ={};//第一次添加元素时知道该 elementData 从空的构造函数还是有参构造函数被初始化的。以便确认如何扩容。private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA ={};transient Object[] elementData;// non-private to simplify nested class accessprivate int size;//数组最大的分配容量private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
构造方法

无参构造方法

当使用默认构造方法时,对象数组指向DEFAULTCAPACITY_EMPTY_ELEMENTDATA容量为0,当第一次添加数据时,将数组的长度扩展为默认大小DEFAULT_CAPACITY。

源码分析:

public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

有参构造方法 初始化数组的长度

源码分析:

public ArrayList(int initialCapacity) {if(initialCapacity > 0) {this.elementData = new Object[initialCapacity];}else if (initialCapacity == 0) {this.elementData = EMPTY_ELEMENTDATA;} else {throw new  IllegalArgumentException("Illegal Capacity: "+ initialCapacity);}
}
添加元素
add(E e):添加 元素List\<Integer> list = new ArrayList<>();list.add(1);

源码分析:

public boolean  add(E e) {ensureCapacityInternal(size + 1);  // 确认容量是否足够elementData[size++] = e;return true ;}

确认最小空间

private void  ensureCapacityInternal( int  minCapacity) {ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

初始化数组空间大小

private static int  calculateCapacity(Object[] elementData, int minCapacity){//如果是空数组,则将数组长度变为DEFAULT_CAPACITY=10;if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {return Math.max(DEFAULT_CAPACITY\*, minCapacity);}return minCapacity;
}

实现数组的扩容处理

private void ensureExplicitCapacity(int minCapacity) {//如果当集合容量+1 > 数组的长度,那么数组要进行扩容if (minCapacity - elementData.length > 0) grow(minCapacity);
}private void grow(int minCapacity) {int oldCapacity = elementData.length;int newCapacity = oldCapacity + (oldCapacity >> 1); //扩容1.5倍if (newCapacity - minCapacity < 0)    newCapacity = minCapacity;if (newCapacity - *MAX_ARRAY_SIZE\* > 0) //超过了数组的最大指newCapacity = *hugeCapacity*(minCapacity);elementData = Arrays.*copyOf*(elementData, newCapacity); //数组扩容}
删除元素remove(int index),根据位置删除:

img

list.remove(1); //删除元素-根据位置删除 

源码分析:

public E remove(int index) {......E oldValue = elementData(index); //删除之前获取旧数据int numMoved = size - index - 1; //要移动的数组元素数量if (numMoved > 0)System.arraycopy(elementData, index+1, elementData, index,numMoved);elementData[--size] = null; //将最后一个元素置为null,数组容量-1return oldValue;
}
删除元素:根据对象内容删除

删除的对象需要实现equals()方法

boolean remove(Object o) //根据对象删除

List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("orange");
list.remove("banana");

源码分析:

我们发现删除时需要调用元素的equals()方法。

public boolean remove(Object o) {if (o == null) {for (int index = 0; index < size; index++)if (elementData[index] == null) {fastRemove(index);return true;}} else { for (int index = 0; index < size; index++)if (o.equals(elementData[index])) {//使用对象的equals方法比较fastRemove(index);return true;}}return false;
}

集合中的类型是String,则使用String中的equals()方法,如果为自定义类型,需要重写对象的equals()方法。

/*** String类中重写了equals()方法*/
public boolean equals(Object anObject) {if (this == anObject) {return true;}if (anObject instanceof String) {String anotherString = (String)anObject;int n = value.length;if (n == anotherString.value.length) {char v1[] = value;char v2[] = anotherString.value;int i = 0;while (n-- != 0) {if (v1[i] != v2[i])return false;i++;}return true;}}return false;}

删除元素源码分析:

private void fastRemove(int index) {int numMoved = size - index - 1;if (numMoved > 0)System.arraycopy(elementData, index+1, elementData, index,numMoved);elementData[--size] = null; // clear to let GC do its work
}
修改元素

E set(int index, E e) 修改元素\

list.set(1, "orange");

源码分析:

public E set(int index, E element) {E oldValue = elementData(index);elementData[index] = element;return oldValue;
}
查询元素

E get(int index) 查询元素

list.get(3);

源码分析:

public E get(int index) {rangeCheck(index);return elementData(index);
} 

LinkedList

什么是链表?

逻辑上连续,空间上不联系,如下图车厢和前后两个车厢相连(双向链表)。

img

如何定义链表(双向链表)
定义节点
private static class Node<E> {E item;Node<E> next; //连接下一个节点的引用Node<E> prev; //连接上一个节点的引用Node(Node<E> prev, E element, Node<E> next) {this.item = element;this.next = next;this.prev = prev;}
}
2头节点即链表的第一个节点。
transient Node<E> first;
尾节点即链表的最后一个节点
 transient Node<E> last;
设计双向链表(LinkedList的实现)

boolean add(E e) //添加节点

源码分析:

public boolean add(E e) {linkLast(e);return true;
}void linkLast(E e) {final Node<E> l = last; //记录尾节点final Node<E> newNode = new Node<>(l, e, null);last = newNode;if (l == null) //链表为空,新节点即为第一个节点first = newNode; //头节点指向新节点elsel.next = newNode; //链表不为空,则尾节点连接新节点size++;:
}

boolean remove(Object o) 删除节点

源码分析:

public boolean remove(Object o) {if (o == null) {for (Node<E> x = first; x != null; x = x.next) {if (x.item == null) {unlink(x);return true;}}} else {for (Node<E> x = first; x != null; x = x.next) {if (o.equals(x.item)) {unlink(x);return true;}}}return false;
}
E unlink(Node<E> x) { //x为要删除的节点对象final E element = x.item;
final Node<E> next = x.next; 
final Node<E> prev = x.prev;if (prev == null) { //删除头节点first = next;
} else {prev.next = next;//删除节点的前一个节点连接后一个节点x.prev = null;
}
if (next == null) {//删除尾节点last = prev;} else {next.prev = prev;//删除节点的后一个节点连接前一个节点x.next = null;
}
x.item = null;
size--;
return element;
}

E set(int index, E element) 修改节点信息

源码分析:

public E set(int index, E element){
Node<E> x = node(index);
E oldVal = x.item;
x.item = element;
return oldVal;
}

public E get(int index) 查询某个节点信息

源码分析:

public E get(int index) {return node(index).item;
}Node<E> node(int index) {
if (index < (size >> 1)) {Node<E> x = first;for (int i = 0; i < index; i++) x = x.next;return x;
} else {Node<E> x = last;for (int i = size - 1; i > index; i--) x = x.prev;return x;}
}

Vector类

Vector 类实现了一个动态数组。。

Vector的类的层次结构

public class Vector<E>extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable

Vector的api

public synchronized boolean add(E e):添加
public synchronized boolean add(E e) {ensureCapacityHelper(elementCount + 1);elementData[elementCount++] = e;return true;
}
public synchronized E remove(int index): 删除
public synchronized E set(int index, E element):修改
public synchronized E get(int index):查询
程序案例:
Vector<String> v = new Vector<>();		
v.add("apple");
v.add("orange");
v.add("banana"); 
v.remove(1);	
v.set(0, "strawberry");		
String f = v.get(1);		
System.*out\*.println(f);
System.*out\*.println(v);

程序运行结果:

banana
[strawberry, banana]

Iterator接口实现元素遍历

迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。

程序案例:

List<String> l = new ArrayList();
l.add("apple");
l.add("orange");
l.add("banana");
for (Iterator<String> iter = l.iterator(); iter.hasNext();) {String str = (String) iter.next();System.*out\*.println(str);
}

Stack类

限定仅在表尾进行插入或删除操作的线性表,表尾—栈顶,表头—栈底,不含元素的空表称空栈。

img\

类的结构

image-20240527174910576

Stack常用API

image-20240527175001995

程序案例:

Stack<Integer> stack = new Stack<>();
stack.push(6);
stack.push(2);
stack.push(5);
stack.push(1);

Queue接口

队列(简称作队)也是一种特殊的线性表,队列的数据元素以及数据元素间的逻辑关系和线性表完全相同,其差别是线性表允许在任意位置插入和删除,而队列只允许在其一端进行插入操作在其另一端进行删除操作。队列中允许进行插入操作的一端称为队尾,允许进行删除操作的一端称为队头。队列的插入操作通常称作入队列,队列的删除操作通常称作出队列。

img

接口结构

image-20240527175136505

Queue常用API

image-20240527175204627

Set接口

set接口是继承自Collection的子接口。

Set接口特性

特点是元素不重复,存储无序。在set接口的实现类中添加重复元素是不会成功的,判断两个元素是否重复根据元素类重写的hashCode()和equals()方法。

Set接口的实现类 HashSet

image-20240527175308483

常用api:

boolean add(E e)boolean remove(Object o)/*底层使用map,删除key*/public boolean remove(Object o) {return map.remove(o)==*PRESENT\*;
}

其它Set接口的实现类

TreeSet<E>

LinkedHashSet<E>

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

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

相关文章

大事件项目实战

初始化 创建项目 新建api_server文件夹为项目根目录&#xff0c;并在项目中运行如下的命令&#xff0c;初始化管理配置文件&#xff1a; npm init -y 运行如下的命令&#xff0c;安装特定版本的express: npm i express4.17.1 在项目根目录中新建app.js作为整个项目的入口…

产品经理-交互说明撰写(八)

1. 交互说明 交互说明可以看做是交互设计师或者产品经理输出的最核心的”产品“交互说明面向的”用户“是下游的同事 ⇒ UI设计师、开发工程师、测试工程师 2. 基本交互形式 2.1 页面交互 2.2 元素控件交互 3. 交互说明主要包括以下3个维度 3.1 页面流程&#xff08;页面之…

医学图像分割--U-net变种

参考&#xff1a;医学图像分割综述:U-Net系列_医学图像 实例分割-CSDN博客 2D Unet 收缩路径&#xff1a;每个块包含两个连续的3 3卷积&#xff0c;后面是一个ReLU激活函数和最大池化层&#xff08;下采样&#xff09;扩展路径&#xff1a;该路径包括一个2 2转置卷积层(上采…

推荐丨免费一年期SSL证书在哪里可以申请到?

当然&#xff0c;申请HTTPS证书的流程可以简化为三个主要步骤&#xff0c;以便理解&#xff1a; 第一步&#xff1a;选择证书类型和认证机构 1. 确定证书类型&#xff1a;首先&#xff0c;你需要确定适合你网站的SSL证书类型。常见的有三种&#xff1a; - 域名验证型&#xff0…

什么是HTTP代理?适用于哪些场景?

HTTP代理是一种网络代理服务器&#xff0c;它主要用于处理HTTP协议的请求和响应。HTTP代理充当客户端&#xff08;如浏览器&#xff09;和目标服务器之间的中介&#xff0c;允许客户端通过代理服务器来发送HTTP请求&#xff0c;并接收来自服务器的响应。HTTP代理可以分为正向代…

时空AI软件:地理信息与遥感领域的智慧引擎

在地理信息与遥感技术的广阔疆域&#xff0c;时空AI软件如同一颗璀璨新星&#xff0c;将时空信息与智能深度融合&#xff0c;驱动着地理信息分析、决策支持、环境监测、城市规划等领域的深刻变革。本文将深入剖析其技术核心、应用实例、未来趋势&#xff0c;探索时空AI软件如何…

自适应容积卡尔曼滤波|(自适应CKF)的MATLAB源代码

介绍 容积卡尔曼滤波在理论上拥有比UKF更高的精度和稳定性&#xff0c;本自适应算法通过对观测残差的计算&#xff0c;在观测协方差R不准确或无法获得时&#xff0c;对R进行调节&#xff0c;以起到降低估计误差的作用。 模型 使用的是三维的非线性模型&#xff0c;经过适当修…

2024年蓝桥杯B组C++——复盘

1、握手问题 知识点&#xff1a;模拟 这道题很简单。但是不知道考试的时候有没有写错。一开始的43个人握手&#xff0c;仅需要两两握手&#xff0c;也就是从42个握手开始&#xff0c;而非43.很可惜。这道题没有拿稳这5分。也很有可能是这5分导致没有进决赛。 总结&#xff1a…

数据集004:跌倒检测数据集 (含数据集下载链接)

数据集简介&#xff1a; 该数据集为跌倒检测数据集&#xff0c;属于imageclassify任务&#xff0c;分为fall和nofall两大类&#xff0c;累计共1000张图片&#xff0c;均为人工标注 xml格式&#xff0c;可用于yolo训练。 数据集链接&#xff1a;跌倒检测数据集&#xff08;1000…

【软件测试】bug篇|软件测试的生命周期|描述bug的要素|bug的级别|bug的生命周期|高频面试题:与开发产⽣争执怎么处理

目录 一、软件测试的⽣命周期 二、BUG 2.1 bug的概念 2.2 描述bug的要素 2.3 bug级别 2.4 bug的⽣命周期 &#x1f4a1;2.5 与开发产⽣争执怎么办&#xff08;⾼频考题&#xff09; &#x1f4a1; 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&…

Python筑基之旅专栏(导航)

目录 一、Python筑基之旅专栏博文清单及链接 二、推荐阅读 一、Python筑基之旅专栏博文清单及链接 01、溯源及发展 02、变量和数据类型 03、搭建Python开发环境及库 04、两个重要函数/列表/元组 05、字符串(一) 06、字符串(二) 07、字符串(三) 08、字典 09、集合 10…

Taro React组件开发 —— RuiVerifySlider 行为验证码之滑动拼图

1. 效果预览 2. 使用场景 账号登录,比如验证码发送,防止无限调用发送接口,所以在发送之前,需要行为验证! 3. 插件选择 AJ-Captcha行为验证码文档AJ-Captcha行为验证码代码仓库为什么要选用【AJ-Captcha行为验证码】呢?因为我们管理后台使用的是 pigx ,它在后端采用的是【…

HX-100调频广播覆盖专用天线

HX-100全向天线是北京恒星科通科技发展有限公司自主研发的一款隧道专用宽带调频发射天线&#xff0c;采用圆盘形结构、振子采用铝合金材料制造&#xff0c;具有增益高、功率容量大、工作频带宽、安装方便、防腐防潮、抗风性能好等特点&#xff0c;特别适合隧道调频广播覆盖、地…

【制作100个unity游戏之26】unity2d横版卷轴动作类游13(附带项目源码)

最终效果 系列导航 文章目录 最终效果系列导航前言存储点灯光后处理存储位置信息存储更多数据存储场景信息持久化存储数据引入Unity 的可序列化字典类调用 游戏结束源码完结 前言 欢迎来到【制作100个Unity游戏】系列&#xff01;本系列将引导您一步步学习如何使用Unity开发各…

拆分字段——kettle开发11

一、拆分字段 1、拆分字段就是将一个字段拆分为多个字段&#xff0c;原字段就不存在数据流之中&#xff0c;拆分的规则是按照一个的分隔符进行拆分。具体语法如下图所示。 2、实操将EXCEL中name拆分为firstname 和 lastname,具体转换包括EXCEL输入、拆分字段、EXCEL输出。 EXC…

《软件方法(下)》8.3.4.5和《设计模式》中用语的区别

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 8.3 建模步骤C-2 识别类的关系 8.3.4 识别关联关系 8.3.4.4 类关系再整理 有了前面的知识&#xff0c;我们需要再整理一下类的关系。用类图表示类的关系如图8-134。 图8-134 “类的…

如何进行硬件监控

在复杂的技术环境中&#xff0c;人们很容易忘记硬件资源的重要性&#xff0c;IT 行业的爆炸性增长使得监控各种硬件资源变得越来越重要&#xff0c;在处理运行关键业务应用程序并在日常基础上启用全局操作的大型网络时&#xff0c;保护这些网络环境的基本构建块至关重要。硬件监…

苗情灾情监控系统—提高农业生产效率

TH-MQ2苗情灾情监控系统是一种用于监测农作物生长状况和灾情的设备&#xff0c;通过实时监测和数据分析&#xff0c;帮助农民及时了解作物生长情况&#xff0c;采取相应的管理措施&#xff0c;提高农业生产效率和降低生产成本。 该系统通常由多种传感器、摄像头、数据传输模块等…

IDEA软件和插件安装

安装IDEA版本&#xff1a;IDEA windows 2021.1.3 使用该版本的IDEA&#xff0c;并且安装下面插件后&#xff0c;个人认为非常好用&#xff0c;并且可以不用破解&#xff0c;无限使用企业版&#xff0c;了解具体方法可以留言或私信。 记录几个好用的IDEA插件&#xff0c;后续持…

安装appium自动化测试环境,我自己的版本信息

教程来自&#xff1a;Appium原理与安装 - 白月黑羽 我的软件的版本&#xff1a; 安装是选择为自己安装而不是选all user pip install appium-python-client命令在项目根目录下安装appium-python-client sdk的话最简单的安装方式就是去Android官网下一个android studio然后在…