【JavaSE专栏30】稀疏数组稀疏在哪?为什么可以节省Java内存空间?

简介: 【JavaSE专栏30】稀疏数组稀疏在哪?为什么可以节省Java内存空间?

本文对 Java 中稀疏数组进行了介绍,讲解了稀疏数组和定义语法、应用场景和优势,并给出了样例代码。

一、什么是稀疏数组

稀疏数组是一种特殊的数组存储结构,用于表示大部分元素值为默认值或者为0的数组。在稀疏数组中,只存储非默认值或非 0 00 的元素及其对应的索引信息,从而节省了存储空间。

与普通数组相比,稀疏数组具有以下区别:

  1. 存储方式:普通数组是按照数组元素的位置顺序依次存储元素值,而稀疏数组则是存储非默认值或非 0 00 的元素以及它们的索引信息。
  2. 存储空间:由于稀疏数组只存储非默认值或非 0 00 的元素,因此相对于普通数组,可以大大减少存储空间的占用。
  3. 访问效率:由于稀疏数组需要先根据索引信息进行定位,然后再获取元素值,因此相对于普通数组,访问效率稍低一些。
  4. 灵活性:稀疏数组可以在一定程度上降低存储和传输的成本,适用于大部分元素值为默认值或者为 0 00 的情况。

在实际应用中,稀疏数组常用于稀疏矩阵、图像处理等需要节省存储空间的场景。

稀疏数组是一种特殊的数组,其中大部分元素具有相同的默认值,并且只有少数元素具有非默认值。稀疏数组通过仅存储非默认值元素的索引和值,以节省内存空间。这种数据结构通常在处理稀疏矩阵或具有大量默认值的数据集时使用。

稀疏数组的定义可以包括以下几个要素:

  1. 原始数组的大小:稀疏数组是基于原始数组创建的,需要记录原始数组的大小。
  2. 非默认值元素的个数:记录稀疏数组中非默认值元素的个数。
  3. 非默认值元素的索引和值:使用一种合适的数据结构(如哈希表、链表等)来存储非默认值元素的索引和值。


二、稀疏数组的应用场景和优势

2.1 应用场景

稀疏数组是一种用于存储大部分元素为默认值(通常为 0 00)的数组,它通过记录非默认值元素的位置和值来节省内存空间,Java 稀疏数组的应用场景有以下四类。

  1. 矩阵和稀疏矩阵存储:在处理矩阵和稀疏矩阵时,往往大部分元素都是 0 00 或者某一默认值。使用稀疏数组可以只存储非默认值的元素,节省内存空间。对于大型矩阵或者稀疏矩阵,这种优化效果尤为明显。
  2. 图的存储:在图的存储中,通常采用邻接矩阵或邻接表的方式。对于稀疏图(边数相对于顶点数较少),采用稀疏数组可以减少存储空间,并且便于快速访问和处理非默认值元素。
  3. 文件压缩和存储:在文件系统中,特别是对于大型的文本文件或者二进制文件,使用稀疏数组可以降低存储空间的占用,提高文件的压缩效率。
  4. 缓存存储:在缓存存储中,如果缓存中的某些数据很少被访问或者保持默认值,可以使用稀疏数组来存储,减少缓存的占用空间。

2.2 优势

  • 节省内存空间:稀疏数组只存储非默认值元素,可以大幅减少内存占用。
  • 快速访问:由于稀疏数组记录了非默认值元素的位置,可以快速定位和访问这些元素,提高访问效率。
  • 方便处理和操作:由于稀疏数组只存储非默认值元素,可以方便地进行插入、删除和修改操作,而不需要对整个数组进行重新分配内存。

需要注意的是,稀疏数组对于稠密数组(大部分元素非默认值)并不适用,因为这种情况下稀疏数组的存储空间占用可能会比稠密数组更大。因此,使用稀疏数组需要根据具体的应用场景和数据特点来进行合理选择。


三、如何定义稀疏数组

稀疏数组是一种数据结构,用于表示大部分元素值为默认值(通常为 0 00n u l l nullnull)的数组。它的设计目的是为了节省存储空间,只存储非默认值的元素及其对应的索引。

以下是用 Java 实现稀疏数组的代码示例,同学们可以复制运行。

public class SparseArray {
    public static int[][] toSparseArray(int[][] array) {
        int rowCount = array.length;
        int colCount = array[0].length;
        int nonZeroCount = 0;
        // 统计非默认值元素个数
        for (int i = 0; i < rowCount; i++) {
            for (int j = 0; j < colCount; j++) {
                if (array[i][j] != 0) {
                    nonZeroCount++;
                }
            }
        }
        // 创建稀疏数组
        int[][] sparseArray = new int[nonZeroCount + 1][3];
        sparseArray[0][0] = rowCount;
        sparseArray[0][1] = colCount;
        sparseArray[0][2] = nonZeroCount;
        // 将非默认值元素存入稀疏数组
        int index = 1;
        for (int i = 0; i < rowCount; i++) {
            for (int j = 0; j < colCount; j++) {
                if (array[i][j] != 0) {
                    sparseArray[index][0] = i;
                    sparseArray[index][1] = j;
                    sparseArray[index][2] = array[i][j];
                    index++;
                }
            }
        }
        return sparseArray;
    }
    public static int[][] fromSparseArray(int[][] sparseArray) {
        int rowCount = sparseArray[0][0];
        int colCount = sparseArray[0][1];
        int[][] array = new int[rowCount][colCount];
        // 将稀疏数组中的非默认值元素还原到原始数组
        for (int i = 1; i < sparseArray.length; i++) {
            int row = sparseArray[i][0];
            int col = sparseArray[i][1];
            int value = sparseArray[i][2];
            array[row][col] = value;
        }
        return array;
    }
}

稀疏数组的应用场景包括以下四点,同学可以尝试使用稀疏数组。

  1. 矩阵计算:对于大规模稀疏矩阵,使用稀疏数组可以减少存储空间和计算复杂度。
  2. 字符串压缩:对于某些字符串,如果大部分字符都是相同的默认值,使用稀疏数组可以有效压缩字符串的存储空间。
  3. 二维游戏地图:对于游戏中的二维地图,如果大部分区域是无用的或者默认的,使用稀疏数组可以减少地图数据的存储空间。
  4. 网络图的表示:对于网络图的邻接矩阵,如果网络稀疏,使用稀疏数组可以减少存储空间和遍历时间。

在以上场景中,稀疏数组可以有效地提高存储效率,并且在需要还原为原始数据时也可以很方便地进行转换


四、总结

本文对 Java 中稀疏数组进行了介绍,讲解了稀疏数组和定义语法、应用场景和优势,并给出了样例代码。在下一篇博客中,将讲解 Java 中的数组排序方式。

相关文章
|
9月前
|
安全 Java 应用服务中间件
Spring Boot + Java 21:内存减少 60%,启动速度提高 30% — 零代码
通过调整三个JVM和Spring Boot配置开关,无需重写代码即可显著优化Java应用性能:内存减少60%,启动速度提升30%。适用于所有在JVM上运行API的生产团队,低成本实现高效能。
1074 3
|
10月前
|
存储 缓存 Java
Java数组全解析:一维、多维与内存模型
本文深入解析Java数组的内存布局与操作技巧,涵盖一维及多维数组的声明、初始化、内存模型,以及数组常见陷阱和性能优化。通过图文结合的方式帮助开发者彻底理解数组本质,并提供Arrays工具类的实用方法与面试高频问题解析,助你掌握数组核心知识,避免常见错误。
|
8月前
|
Java 大数据 Go
从混沌到秩序:Java共享内存模型如何通过显式约束驯服并发?
并发编程旨在混乱中建立秩序。本文对比Java共享内存模型与Golang消息传递模型,剖析显式同步与隐式因果的哲学差异,揭示happens-before等机制如何保障内存可见性与数据一致性,展现两大范式的深层分野。(238字)
247 4
|
8月前
|
存储 缓存 Java
【深入浅出】揭秘Java内存模型(JMM):并发编程的基石
本文深入解析Java内存模型(JMM),揭示synchronized与volatile的底层原理,剖析主内存与工作内存、可见性、有序性等核心概念,助你理解并发编程三大难题及Happens-Before、内存屏障等解决方案,掌握多线程编程基石。
|
9月前
|
缓存 监控 Kubernetes
Java虚拟机内存溢出(Java Heap Space)问题处理方案
综上所述, 解决Java Heap Space溢出需从多角度综合施策; 包括但不限于配置调整、代码审查与优化以及系统设计层面改进; 同样也不能忽视运行期监控与预警设置之重要性; 及早发现潜在风险点并采取相应补救手段至关重要.
1017 17
|
9月前
|
Java
Java 数组学习笔记
本文整理Java数组常用操作:遍历、求和、查找、最值及二维数组行求和等典型练习,涵盖静态初始化、元素翻倍、去极值求平均等实例,帮助掌握数组基础与应用。
|
10月前
|
监控 Kubernetes Java
最新技术栈驱动的 Java 绿色计算与性能优化实操指南涵盖内存优化与能效提升实战技巧
本文介绍了基于Java 24+技术栈的绿色计算与性能优化实操指南。主要内容包括:1)JVM调优,如分代ZGC配置和结构化并发优化;2)代码级优化,包括向量API加速数据处理和零拷贝I/O;3)容器化环境优化,如K8s资源匹配和节能模式配置;4)监控分析工具使用。通过实践表明,这些优化能显著提升性能(响应时间降低40-60%)同时降低资源消耗(内存减少30-50%,CPU降低20-40%)和能耗(服务器功耗减少15-35%)。建议采用渐进式优化策略。
559 2
|
Java 物联网 数据处理
Java Solon v3.2.0 史上最强性能优化版本发布 并发能力提升 700% 内存占用节省 50%
Java Solon v3.2.0 是一款性能卓越的后端开发框架,新版本并发性能提升700%,内存占用节省50%。本文将从核心特性(如事件驱动模型与内存优化)、技术方案示例(Web应用搭建与数据库集成)到实际应用案例(电商平台与物联网平台)全面解析其优势与使用方法。通过简单代码示例和真实场景展示,帮助开发者快速掌握并应用于项目中,大幅提升系统性能与资源利用率。
327 6
Java Solon v3.2.0 史上最强性能优化版本发布 并发能力提升 700% 内存占用节省 50%