【Java 集合】集合框架 JCF


本文使用 JDK 版本为 JDK1.15

一、概述

  • Java集合框架(JCF, Java Collectioin Framework),它下辖各种常用的数据结构,比如:线性表、队列、栈、红黑二叉树等等。

  • 我们常用集合对数据进行临时存储;本篇文章的脉络 按照 数据结构 进行分类汇总,下面我们介绍 JCF 体系中,接口与类之间的关系。
    JCF结构图、图例

二、List - 线性表

1、ArrayList(顺序存储)

  • 本质上是一个动态数组

重要的内部属性 / 方法
1、为空时,数组的大小默认为0
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
2、添加第一个元素时,数组的默认大小为10
private static final int DEFAULT_CAPACITY = 10;
3、最大容量(2147483647 - 8,一些虚拟机在数组中保留一些头字,尝试分配较大的数组可能会导致OutOfMemoryError:请求的数组大小超过了VM限制):
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
4、本源数组:
transient Object[] elementData;
5、数组扩容方法 --> grow(当数组元素仅剩一个空位时进行扩容,扩容后数组容量为原数组的1.5倍):在这里插入图片描述

无参构造方法:适合数量不确定时使用:
无参构造方法
含参构造方法:适合已知(大致)数量,给定初始大小,以尽可能减少扩容开销【参数 initialCapacity 即为初始大小】:
含参构造方法

2、LinkedList(链式存储 - 双向链表)

  • 本质上是一个链表结构

重要的内部属性 / 类
1、首尾节点:
transient Node<E> first;
transient Node<E> last;
2、内部类 Node
内部节点类Node

3、Vector(顺序存储)

  • 本质上是一个动态数组
  • 底层大量使用synchronized关键字,线程安全

 List - 基本操作

List的基本操作如下(我们以 ArrayList 为例):

//构建 ArrayList 线性表
List<String> list = new ArrayList<>();
//添加数据
list.add("a");
list.add("b");
list.add("c");
list.add("c");
//打印查看线性表内元素
System.out.println(list);
//按索引获取数据
System.out.println("获取 索引为1 的数据: " + list.get(1));
//获取 list 的长度
System.out.println("获取 list 的长度: " + list.size());
//按索引更改元素值
list.set(1, "贰");
//打印查看线性表内元素
System.out.println(list);
//按索引删除元素
list.remove(1);
//打印查看线性表内元素
System.out.println(list);
//首次出现元素索引
System.out.println("首次出现元素 c 的位置索引:" + list.indexOf("c"));
//最后一次出现元素索引
System.out.println("最后一次出现元素 c 的位置索引:" + list.lastIndexOf("c"));
//判断线性表是否为空
System.out.println("判断元素是否为空: " + (list.isEmpty() ? "空" : "非空"));
//清空所有数据
list.clear();
System.out.println("判断元素是否为空: " + (list.isEmpty() ? "空" : "非空"));

运行结果如下:
运行结果

三、Queue (Deque) - 队列(双向队列)

队列(Queue)是一种 特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。

  • 在Java中,Queue是一个接口,实现这个接口的类可以使用队列的基本操作。
  • 队列的特点是先进先出(First In First Out, FIFO),队列就像我们排队的时候,先来的人总是先离开队伍。
  • 队列是一种常见的数据结构,不仅在应用程序中广泛使用,在操作系统中 ,也常常采用队列及其变种形式,来处理各种复杂的进程、线程调度问题。
  • 实现其子接口 Deque 可实现双向队列的操作,其拥有 队列 两种操作方式。
    队列

 Queue - 基本操作

队列的基本操作(包括 Java语言 自带的方法,但仅限于 Queue 接口自己的方法,加粗为队列常用方法):

  1. 进队列 offer(元素从尾部进队列)
  2. 出队列 poll(元素从头部出队列):返回值为队头元素(队列元素为空,返回null)
  3. 移除 remove(元素从头部出队列):返回值为队头元素(队列元素为空,抛出NoSuchElementException异常)
  4. 观察 element(获取队头元素,不出队列):返回值为队头元素(队列元素为空,抛出NoSuchElementException异常)
  5. 窥视 peek(获取队头元素,不出队列):返回值为队头元素(队列元素为空,返回null)

队列的基本操作
具体操作详见其 实现类 之一:LinkedList

→ LinkedList(双向队列)

  • 双向队列意味着它可以当作 堆栈队列 使用,更加灵活,同时由于它还持有 双向链表 的操作,使得它可以根据我们的需要灵活操作。

① 单向队列 - 基本操作

//创建 队列(双向队列)
Queue<String> queue = new LinkedList<>();
//进队列
queue.offer("a");
queue.offer("b");
queue.offer("c");
//打印展示  进队列 offer 操作:
System.out.println("a、b、c 进队尾:");
System.out.println("查看此时队列内情况:" +"\t"+ queue);
//打印展示  出队列 poll 操作,栈顶元素弹出
System.out.println("poll 队头元素出队列:" +"\t"+ queue.poll());
//打印此时栈内情况
System.out.println("查看此时栈内情况:" +"\t"+ queue);
//打印展示  窥视 peek 操作
System.out.println("peek 窥视(获取)栈顶元素:" +"\t"+ queue.peek());
//打印
System.out.println("查看此时栈内情况:" +"\t"+"\t"+ queue);

运行结果如下:
运行结果

② 双向队列 - 基本操作(实现接口 Deque)

  • 双向队列拥有 队列 的所有基本操作方式(栈:push、pop,队列:offer、poll、peek、remove、element),并且拥有offerFirst、offerLast、pollFirst、pollLast、peekFirst、peekLast、removeFirst、removeLast 等独有操作方式。

四、Stack - 栈

栈(stack)又名堆栈,它是一种 运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。

  • 在Java中,Stack是一个,实现这个接口的类可以使用栈的基本操作。
  • 队列的特点是后进先出(Last In First Out, LIFO),Java 的 Stack)继承自 Vector ,所以它具有 Vector 的全部方法(基于数组实现),且自己的部分方法也被synchronized所修饰,所以 Stack 也是线程安全的(push 操作 除外)。
  • 栈就像一个桶,后放进去的元素先出来,先放进去的元素在桶底,直到最后才能出桶。
    栈

 Stack - 基本操作

栈的基本操作(包括 Java语言 自带的方法,但仅限于 Stack 类自己的方法,加粗为栈结构核心操作):

  1. 压栈 push(元素从顶部进栈)
  2. 弹出 pop(获取栈顶元素,出栈):返回值为栈顶元素
  3. 窥视 peek(获取栈顶元素,不出栈):返回值为栈顶元素
    peek视角
  4. 判空 empty(判断是否为空栈,即元素数为0):返回值为布尔类型
  5. 查询 search(查询栈中是否包含元素(与数量无关)):若有则返回与栈顶距离最近的位置,若无则返回-1)

栈的基本操作

//创建 栈
Stack<String> stack = new Stack<>();
//压栈
stack.push("a");
stack.push("b");
stack.push("c");
//打印展示  压栈 push 操作
System.out.println("a、b、c 分别进栈:");
System.out.println("查看此时栈内情况:" +"\t"+ stack);
//打印展示  出栈 pop 操作,栈顶元素弹出
System.out.println("pop 弹出栈顶元素:" +"\t"+ stack.pop());
//打印此时栈内情况
System.out.println("查看此时栈内情况:" +"\t"+ stack);
//打印展示  窥视 peek 操作
System.out.println("peek 窥视(获取)栈顶元素:" +"\t"+ stack.peek());
//打印
System.out.println("查看此时栈内情况:" +"\t"+"\t"+ stack);
//判断此时是否为空栈(也可使用继承方法isEmpty)
System.out.println("判断此时是否为空栈:" +"\t"+"\t"+ (stack.empty()?"是":"否"));
//分别寻找元素a、c(与数量无关)
System.out.println("查询栈内是否存在a元素:" +"\t"+ (stack.search("a")));
System.out.println("查询栈内是否存在c元素:" +"\t"+ (stack.search("c")));
//打印
System.out.println("查看此时栈内情况:" +"\t"+"\t"+ stack);

运行结果如下:
运行结果

五、Map - 键值对(映射)

键值对(映射)存储是存储数据的一种简单的组织形式。
:就是存的值的编号(具有唯一性)。
:就是要存放的数据

1、HashTable

  • Java 中较为经典的 键值对 结构,它的大部分方法被关键字synchronized修饰,所以它 线程安全
  • 它的 Key、Value 均不可为 null,否则会抛出异常NullPointerException(可以做添加 null 的操作,但仍会抛出异常)

2、HashMap

  • Java 中受欢迎的 键值对(Entry<K,V>) 结构,它的底层基于数组 + 链表 / 红黑树 实现,数组中每个元素都是一个 链表 / 红黑树
  • 可作简单缓存,介于关系数据库与操作之间。
  • 它的 Key、Value 均可为 null,存储 null 并不会抛出异常。

重要属性
1、初始数组大小(16)
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
2、数组最大长度(230,基本等同于int最大值231,但会预留部分空间)
static final int MAXIMUM_CAPACITY = 1 << 30;
3、负载因子(当超过当前容量的0.75时,map就会自动扩容。)
static final float DEFAULT_LOAD_FACTOR = 0.75f;
在 jdk1.8 以后,当数组长度超过64,链表内元素数 超过8 时则会 转化红黑树 以提高查询效率,当红黑树元素数 小于6 时,则会 退化链表
4、树化阈值 / 退链阈值
static final int TREEIFY_THRESHOLD = 8;
static final int UNTREEIFY_THRESHOLD = 6;
5、维持树形最小数组容量(4 * 化树阈值,最小即为64),如果一个数组元素中的节点太多,则会调整表的大小。
static final int MIN_TREEIFY_CAPACITY = 64;
6、键值对 Interface Entry<K,V>
Entry

HashMap 基本操作:

//创建HashMap结构
Map<Integer,String> map = new HashMap<>();
//放入对应值
map.put(1,"qwe");
map.put(2,"asd");
map.put(3,"zxc");
//打印获取 map 内的元素
System.out.println("打印获取map内的键值对:" + map);
//按Key 获取 Value
System.out.println("获取Key为2的Value:" + map.get(2));
//获取 map 的大小
System.out.println("获取 map 的大小:" + map.size());
//按Key 替换 Value
map.replace(1,"ABC");
//打印获取 map 内的元素
System.out.println("打印获取map内的键值对:" + map);
//覆写(再次 put 放入)
map.put(2,"159");
//打印获取 map 内的元素
System.out.println("打印获取map内的 键值对:" + map);
//移除 元素(返回值为 对应 Value)
System.out.println("打印获取移除的 Value:" + map.remove(3));
//打印获取 map 内的元素
System.out.println("打印获取map内的键值对:" + map);

运行结果如下:
运行结果

六、Set - 集

  • Set 中的元素具有 唯一性,即:有序不重复

→ HashSet

  • Java 中一种常用的 Set 结构,底层依赖 HashMap,HashSet 依靠 HashMap 的Key 保证其唯一性。

HashSet 基本操作:

//创建HashSet结构
Set<String> set = new HashSet<>();
set.add("abc");
set.add("def");
set.add("ghi");
//是否包含元素 "def"
System.out.println("包含元素 \"def\"?" + (set.contains("def")?"包含":"不包含"));
//移除 元素 "ghi"
System.out.println("移除 \"ghi\" 是否成功:" + (set.remove("ghi")?"是":"否"));
//获取 set 的大小
System.out.println("set 的大小:" + set.size());
//清空 set
System.out.println("清空 set");
set.clear();
//获取 set 的大小
System.out.println("set 的大小:" + set.size());

运行结果如下:
运行结果

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值