当前位置: 首页 > news >正文

容器学习之SparseArray源码解析

1、SparseArray是android sdk 提供集合类,主要用来替换key 为int类型,value为Object类型的Hashmap

2、SparseArray和HashMap相比优缺点:
优点:
1、SparseArray存在一个int[]keys, 因此避免自动装箱
2、SparseArray扩容时只需要数组拷贝工作(system.arraycopy), 不需要重建哈希表(rehash十分消耗性能)
缺点:
3、SparseArray以时间换空间,由于使用二分查找,时间比hashmap要慢。mkeys数组的元素总是连续的(即使中间会存在DELETED元素,但是这些DELETED元素,在后续的gc()方法中被清除掉),不像hashmap数组的元素,由于内在的hash冲突无法彻底解决而导致数组空间利用很浪费。
4、不适合大容量的数据存储。存储大量数据时,他的性能很差,千条数据以内可以使用SparseArray
5、按照key进行自然排序
二、全局变量
//用于标记当前是否有待垃圾回收(GC)的元素
private boolean mGarbage = false

key 数组和value数组的默认打下是10

 //设置数组的默认初始容量为10public SparseArray() {this(10);}/*** Creates a new SparseArray containing no mappings that will not* require any additional memory allocation to store the specified* number of mappings.  If you supply an initial capacity of 0, the* sparse array will be initialized with a light-weight representation* not requiring any additional array allocations.*/public SparseArray(int initialCapacity) {if (initialCapacity == 0) {mKeys = EmptyArray.INT;mValues = EmptyArray.OBJECT;} else {mValues = ArrayUtils.newUnpaddedObjectArray(initialCapacity);mKeys = new int[mValues.length];}mSize = 0;}

添加元素、
主要看put(int key,E value)方法,当中用到了ContainerHelpers类提供binarySearch,用于查找目标key在mKeys中的当前索引或者目标索引
binarySearch方法的返回值分为两种情况:
1.如果mKeys中存在对应的key,则直接返回对应的索引值
2.如果mKeys中不存在对应的key

2.1  假设mKeys中存在"值比key大且大小与key最接近的值的索引为parseIndex",则此方法的返回值为~parsentIndex
2.2 如果mKeys中不存在比key还要大的值的话,则返回值~mKeys.length

通过这种方式来存放数据,可以使得mKeys的内部值一直是按照递增的方式来排序的。

//将索引 index 处的元素赋值为 value//SparseArray 的元素值都是存到 mValues 中的,因此如果知道目标位置(index),则可以直接向数组 mValues 赋值public void setValueAt(int index, E value) {//如果需要则先进行垃圾回收if (mGarbage) {gc();}mValues[index] = value;}/*** Adds a mapping from the specified key to the specified value,* replacing the previous mapping from the specified key if there* was one.*/public void put(int key, E value) {//用二分查找法查找指定 key 在 mKeys 中的索引值int i = ContainerHelpers.binarySearch(mKeys, mSize, key);//找得到则直接赋值if (i >= 0) {mValues[i] = value;} else {//binarySearch 方法的返回值分为两种情况://1、如果存在对应的 key,则直接返回对应的索引值//2、如果不存在对应的 key//  2.1、假设 mKeys 中存在"值比 key 大且大小与 key 最接近的值的索引"为 presentIndex,则此方法的返回值为 ~presentIndex//  2.2、如果 mKeys 中不存在比 key 还要大的值的话,则返回值为 ~mKeys.length//可以看到,即使在 mKeys 中不存在目标 key,但其返回值也指向了应该让 key 存入的位置//通过将计算出的索引值进行 ~ 运算,则返回值一定是 0 或者负数,从而与“找得到目标key的情况(返回值大于0)”的情况区分开//且通过这种方式来存放数据,可以使得 mKeys 的内部值一直是按照值递增的方式来排序的i = ~i;//如果目标位置还未赋值,则直接存入数据即可,对应的情况是 2.1if (i < mSize && mValues[i] == DELETED) {mKeys[i] = key;mValues[i] = value;return;}//以下操作对应两种情况://1、对应 2.1 的一种特殊情况,即目标位置已用于存放其他值了//   此时就需要将从索引 i 开始的所有数据向后移动一位,并将 key 存到 mKeys[i]//2、对应的情况是 2.2if (mGarbage && mSize >= mKeys.length) {gc();//GC 后再次进行查找,因为值可能已经发生变化了i = ~ContainerHelpers.binarySearch(mKeys, mSize, key);}//通过复制或者扩容数组,将数据存放到数组中mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key);mValues = GrowingArrayUtils.insert(mValues, mSize, i, value);mSize++;}}//和 put 方法类似//但在存入数据前先对数据大小进行了判断,有利于减少对 mKeys 进行二分查找的次数//所以在“存入的 key 比现有的 mKeys 值都大”的情况下会比 put 方法性能高public void append(int key, E value) {if (mSize != 0 && key <= mKeys[mSize - 1]) {put(key, value);return;}if (mGarbage && mSize >= mKeys.length) {gc();}mKeys = GrowingArrayUtils.append(mKeys, mSize, key);mValues = GrowingArrayUtils.append(mValues, mSize, value);mSize++;}

上文说:布尔变量mGarbage用于标记当前是否有待垃圾回收(GC)的元素,当该值为true时,即意味着当前状态需要垃圾回收,回收操作不是立马进行的,而是在后续操作中完成。

以下几个方法在移除元素时,只是切断mValues中的引用,而mKeys没进行回收,这个操作gc()进行处理。

 //如果存在 key 对应的元素值,则将其移除public void delete(int key) {//用二分查找法查找指定 key 在 mKeys 中的索引值int i = ContainerHelpers.binarySearch(mKeys, mSize, key);if (i >= 0) {if (mValues[i] != DELETED) {mValues[i] = DELETED;//标记当前需要进行垃圾回收mGarbage = true;}}}public void remove(int key) {delete(key);}//和 delete 方法基本相同,差别在于会返回 key 对应的元素值public E removeReturnOld(int key) {int i = ContainerHelpers.binarySearch(mKeys, mSize, key);if (i >= 0) {if (mValues[i] != DELETED) {final E old = (E) mValues[i];mValues[i] = DELETED;mGarbage = true;return old;}}return null;}//删除指定索引对应的元素值public void removeAt(int index) {if (mValues[index] != DELETED) {mValues[index] = DELETED;//标记当前需要进行垃圾回收mGarbage = true;}}//删除从起始索引值 index 开始之后的 size 个元素值public void removeAtRange(int index, int size) {//避免发生数组越界的情况final int end = Math.min(mSize, index + size);for (int i = index; i < end; i++) {removeAt(i);}}//移除所有元素值public void clear() {int n = mSize;Object[] values = mValues;for (int i = 0; i < n; i++) {values[i] = null;}mSize = 0;mGarbage = false;}

垃圾回收、
因为SparseArray中可能会出现只移除value和value两者之一的情况,导致数组存在无效引用,因此gc()方法就用于移除无效引用,并将有效的元素值位置合在一起

//垃圾回收//因为 SparseArray 中可能出现只移除 value 和 value 两者之一的情况//所以此方法就用于移除无用的引用private void gc() {int n = mSize;//o 值用于表示 GC 后的元素个数int o = 0;int[] keys = mKeys;Object[] values = mValues;for (int i = 0; i < n; i++) {Object val = values[i];//元素值非默认值 DELETED ,说明该位置可能需要移动数据if (val != DELETED) {//以下代码片段用于将索引 i 处的值赋值到索引 o 处//所以如果 i == o ,则不需要执行代码了if (i != o) {keys[o] = keys[i];values[o] = val;values[i] = null;}o++;}}mGarbage = false;mSize = o;}

相关文章:

容器学习之SparseArray源码解析

1、SparseArray是android sdk 提供集合类&#xff0c;主要用来替换key 为int类型&#xff0c;value为Object类型的Hashmap 2、SparseArray和HashMap相比优缺点&#xff1a; 优点&#xff1a; 1、SparseArray存在一个int[]keys, 因此避免自动装箱 2、SparseArray扩容时只需要数…...

信创改造技术介绍

目录 服务发现和注册 Sentinel 核心功能 典型应用场景 gateway 网关的主要功能 Spring Cloud Gateway Kong Kong 的主要功能 Kong 的架构&#xff1a; Kong 的使用场景&#xff1a; Kong 的部署模式&#xff1a; 优势 Gateway与Sentinel区别 Gateway Sentinel …...

【可见的点——欧拉函数】

在数论&#xff0c;对正整数n&#xff0c;欧拉函数是小于或等于n的正整数中与n互质的数的数目&#xff08;不包括1&#xff09; 题目 思路 有三个点比较特殊&#xff08;因为一来这三个点一定可见&#xff0c;同时也无法用gcd 1判断&#xff09;&#xff1a;&#xff08;0&am…...

Maven重点学习笔记(包入门 2万字)

Maven依赖管理项目构建工具 尚硅谷 5h 2023最新版 一&#xff0c;Maven简介 1.为什么学习Maven 1.1, Maven是一个依赖管理工具 1️⃣ jar包的规模 随着我们使用越来越多的框架&#xff0c;或者框架封装程度越来越高&#xff0c;项目中使用的jar包也越来越多。项目中&…...

1.分页查询(后端)—— Vue3 + SpringCloud 5 + MyBatisPlus + MySQL 项目系列(基于 Zulu 11)

本手册是基于 Vue3 SpringCloud5 MyBatisPlus MySQL 的项目结构和代码实现&#xff0c;旨在作为一个教学案例进行讲解。为了使案例更具普适性&#xff0c;文档中的公司名称、实体类、表名以及字段名称等敏感信息均已脱敏。 项目结构概述 项目采用标准的分层架构&#xff0…...

机器学习与深度学习的区别:深入理解与应用场景

在人工智能&#xff08;AI&#xff09;的广阔领域中&#xff0c;机器学习和深度学习是两个核心概念&#xff0c;它们虽然紧密相关&#xff0c;但在定义、技术、数据处理能力、应用场景等方面存在显著差异。本文将深入探讨这些区别&#xff0c;帮助读者更好地理解并选择合适的技…...

C++学习笔记(45)

322、循环队列、信号量、生产/消费者模型的源代码 一、demo1.cpp // demo1.cpp&#xff0c;本程序演示循环队列的使用。 #include "_public.h" int main() { using ElemTypeint; squeue<ElemType,5> QQ; ElemType ee; // 创建一个数据元素。 cout << &qu…...

【2】图像视频的加载和显示

文章目录 【2】图像视频的加载和显示一、代码在哪写二、创建和显示窗口&#xff08;一&#xff09;导入OpenCV的包cv2&#xff08;二&#xff09;创建窗口&#xff08;三&#xff09;更改窗口大小 & 显示窗口&#xff08;四&#xff09;等待用户输入补充&#xff1a;ord()函…...

1. BOOT.BIN 2. 固化 3. 启动 4. SDK 5. 文件

在进行FPGA的开发与固化过程中&#xff0c;生成BOOT.BIN文件是一个重要的步骤。BOOT.BIN文件通常包含了系统启动所需的不同文件&#xff0c;以下是如何创建和使用该文件的详细说明。 ### 生成BOOT.BIN文件的步骤 1. **方法一&#xff1a;通过项目构建** - 右键单击项目&#xf…...

vue按钮接收键盘回车事件

了解了&#xff01;如果您想让 Submit 按钮在按下回车键时被触发&#xff0c;可以在 Vue 组件中监听全局的键盘事件。以下是实现这一功能的示例&#xff1a; 示例代码 <template><div><inputtype"text"v-model"inputValue"placeholder&qu…...

腾讯云点播及声音上传

文章目录 1、开通腾讯云点播2、获取腾讯云API密钥3、完成声音上传3.1、引入依赖3.2、参考&#xff1a;接入点地域3.3、参考&#xff1a;任务流设置3.4、首先修改配置&#xff1a;3.4.1、 3.5、TrackInfoApiController --》 uploadTrack()3.6、VodServiceImpl --》 uploadTrack(…...

如何查看服务器是否有raid阵列卡以及raid类型

要查看服务器是否配置了RAID阵列卡以及RAID的类型&#xff0c;可以使用多种方法。以下是一些常用的命令和步骤&#xff1a; 1. 使用 lspci 命令 这个命令可以列出所有的PCI设备&#xff0c;包括RAID控制器。 lspci | grep -i raid 如果输出中有RAID相关的设备信息&#xff0c;那…...

工博会动态 | 来8.1馆 看桥田如何玩转全场

北京时间2024年9月24日&#xff0c;中国国际工业博览会开幕&#xff0c;桥田智能&#xff08;8.1馆A001&#xff09;推出心意三重奏&#xff0c;有没有小伙伴们发现呢&#xff1f;现在&#xff0c;让我们一起city walk下&#xff01; 桥田显眼包横空出道 有小伙伴已经发现&…...

新版torch_geometric不存在uniform、maybe_num_nodes函数问题(Prune4ED论文报错解决)

这是在复现论文“Towards accurate subgraph similarity computation via neural graph pruning”时遇到的报错。 ImportError: cannot import name uniform from torch_geometric.nn.pool.topk_pool 一、报错原因 论文作者使用的是2.1.0版本的torch_geometric。而我安装了2.…...

实现简易 vuedraggable 的拖拽排序功能

一、案例效果 拖拽计数4实现手动排序 二、案例代码 <draggable:list"searchResult.indicator":group"{ name: indicators }"item-key"field"handle".drag-handle-icon"><divclass"field-item"v-for"(item…...

第L2周:机器学习|线性回归模型 LinearRegression:2. 多元线性回归模型

本文为365天深度学习训练营 中的学习记录博客原作者&#xff1a;K同学啊 任务&#xff1a; ●1. 学习本文的多元线形回归模型。 ●2. 参考文本预测花瓣宽度的方法&#xff0c;选用其他三个变量来预测花瓣长度。 一、多元线性回归 简单线性回归&#xff1a;影响 Y 的因素唯一&…...

JavaScript的条件语句

if条件语句 if结构先判断一个表达式的布尔值&#xff0c;然后根据布尔值的真伪&#xff0c;执行不同的语句。所谓布尔值&#xff0c;指的是JavaScript 的两个特殊值&#xff0c;true表示真&#xff0c;false表示伪。 if语句语法规范 if(布尔值){语句;}var m3if(m3){console.l…...

vue3 vite模式配置测试,开发、生产环境以及代理配置

1、首先在根目录下创建三个文本文件&#xff1a;.env.development&#xff0c;.env.production&#xff0c;.env.test .env.development中的内容为&#xff1a; // 开发环境 .env.development NODE_ENV development VITE_APP_MODE development VITE_OUTPUTDIR dist_dev /…...

【rabbitmq-server】安装使用介绍

在 1050a 系统下安装 rabbitmq-server 服务以及基本配置;【注】:改方案用于A版统信服务器操作系统 文章目录 功能概述功能介绍一、安装软件包二、启动服务三、验证四、基本配置功能概述 RabbitMQ 是AMQP的实现,高性能的企业消息的新标准。RabbitMQ服务器是一个强大和可扩展…...

Kafka系列之:安装部署CMAK,CMAK管理大型Kafka集群参数调优

Kafka系列之:安装部署CMAK,CMAK管理大型Kafka集群参数调优 一、CMAK二、要求三、配置四、启动服务五、使用 Security 启动服务六、消费者/生产者滞后七、从 Kafka Manager 迁移到 CMAK八、CMAK管理大型Kafka集群参数调优九、后台运行CMAK十、输出日志一、CMAK CMAK(之前称为…...

五年级数学知识边界总结思考-下册

目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解&#xff1a;由来、作用与意义**一、知识点核心内容****二、知识点的由来&#xff1a;从生活实践到数学抽象****三、知识的作用&#xff1a;解决实际问题的工具****四、学习的意义&#xff1a;培养核心素养…...

ffmpeg(四):滤镜命令

FFmpeg 的滤镜命令是用于音视频处理中的强大工具&#xff0c;可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下&#xff1a; ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜&#xff1a; ffmpeg…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

Reasoning over Uncertain Text by Generative Large Language Models

https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...

push [特殊字符] present

push &#x1f19a; present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中&#xff0c;push 和 present 是两种不同的视图控制器切换方式&#xff0c;它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...

Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?

Pod IP 的本质与特性 Pod IP 的定位 纯端点地址&#xff1a;Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址&#xff08;如 10.244.1.2&#xff09;无特殊名称&#xff1a;在 Kubernetes 中&#xff0c;它通常被称为 “Pod IP” 或 “容器 IP”生命周期&#xff1a;与 Pod …...

Oracle11g安装包

Oracle 11g安装包 适用于windows系统&#xff0c;64位 下载路径 oracle 11g 安装包...

02.运算符

目录 什么是运算符 算术运算符 1.基本四则运算符 2.增量运算符 3.自增/自减运算符 关系运算符 逻辑运算符 &&&#xff1a;逻辑与 ||&#xff1a;逻辑或 &#xff01;&#xff1a;逻辑非 短路求值 位运算符 按位与&&#xff1a; 按位或 | 按位取反~ …...

STM32标准库-ADC数模转换器

文章目录 一、ADC1.1简介1. 2逐次逼近型ADC1.3ADC框图1.4ADC基本结构1.4.1 信号 “上车点”&#xff1a;输入模块&#xff08;GPIO、温度、V_REFINT&#xff09;1.4.2 信号 “调度站”&#xff1a;多路开关1.4.3 信号 “加工厂”&#xff1a;ADC 转换器&#xff08;规则组 注入…...