Java 数组

Java 数组,第1张

Java 数组

Java 数组
  • 一、数组概述
  • 二、数组的声明与创建
    • 2.1 数组的声明
    • 2.2 数组的创建
  • 三、数组使用
    • 3.1 Java 内存(简要分析)
      • 3.1.1 堆
      • 3.1.2 栈
      • 3.1.3 方法区
    • 3.2 初始化
      • 3.2.1 静态初始化
      • 3.2.2 动态初始化
    • 3.3 数组的基本特点
    • 3.4 For-Each 循环
    • 3.5 数组作为方法参数
  • 四、多维数组
    • 4.1 初始化
      • 4.1.1 静态初始化
      • 4.1.2 动态初始化
        • 1. 直接为每一维分配空间
        • 2. 从最高维开始,分别为每一维分配空间
  • 五、Arrays 类
  • 六、稀疏数组
    • 6.1 稀疏数组引入
    • 6.2 稀疏数组介绍

一、数组概述
  • 数组是固定大小的相同类型数据的有序集合。
  • 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。
  • 数组中的每一个数据被称作一个数组元素,每个数组元素可以通过一个下标来访问它们。
二、数组的声明与创建 2.1 数组的声明

quad 首先,必须声明数组变量,才能在程序中使用数组。声明数组变量的语法:dataType[] arrayRefVar;或 dataType arrayRefVar[];,其中 dataType 为数据类型,arrayRefVar 为数组变量名。

quad 注:建议使用 dataType[] arrayRefVar 的声明风格声明数组变量。dataType arrayRefVar[] 风格是来自 C/C++ 语言 ,在 Java 中采用是为了让 C/C++ 程序员能够快速理解 Java 语言。

2.2 数组的创建
  • Java 语言使用 new 关键字来创建数组,语法:arrayRefVar = new dataType[arraySize];。这个语句做了两件事:

    • 使用 dataType[arraySize] 创建了一个数组,其中 arraySize 为数组长度,即数组可以存储数据的最大数量。
    • 把新创建的数组的引用赋值给变量 arrayRefVar。
  • 你还可以使用直接赋值数组的方式创建数组:dataType[] arrayRefVar = {value0, value1, ..., valuek};,其中 value0, value1, ..., valuek 为数组中存储的数据。

  • 数组的声明和创建可以用一条语句完成:dataType[] arrayRefVar = new dataType[arraySize];

三、数组使用

quad 数组的元素是通过索引访问的。数组索引从 0 开始,所以索引值从 0 到 arrayRefVar.length-1,其中 arrayRefVar.length 返回数组的长度。如果索引不在 [0,arrayRefVar.length-1] 范围,则报 ArrayIndexOutOfBoundsException 数组下标越界异常。

3.1 Java 内存(简要分析)

quad 数组在 Java 内存存储的情形大致如下:

3.1.1 堆
  • 存放 new 的对象和数组。
  • 可以被所有的线程共享,不会存放别的对象引用。
3.1.2 栈
  • 存放基本变量类型(会包含这个基本类型的具体数值)
  • 存放引用对象的变量(会存放这个引用在堆里面的具体地址)
3.1.3 方法区
  • 存放所有的 class 和 static 变量。
  • 可以被所有的线程共享
3.2 初始化

quad Java 数组必须先初始化,然后才可以被使用。所谓初始化就是为数组的数组元素分配内存空间,并为每个数组元素赋初始值。

3.2.1 静态初始化
  • 初始化时由开发人员显式地指定每个数组元素的初始值,由 JVM 决定数组的长度。
  • 示例:int[] array = {10,20,30,40,50,60,70,80,90};
3.2.2 动态初始化
  • 初始化时由开发人员指定数组的长度,由 JVM 初始化每个数组元素的默认值。
  • 数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。
  • 示例:double[] array = new double[10]; 默认值:0.0。
3.3 数组的基本特点
  • 数组长度是固定的。数组一旦被创建,它的大小就是不可以被改变的。
  • 数组中的元素必须是相同类型,不允许出现混合类型。
  • 数组中的元素可以是任何数据类型,包括基本类型和引用类型。
  • 数组变量属于引用类型,可以被看成对象,数组中的每个元素相当于该对象的成员变量。
  • 数组本身就是对象,Java 中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的。
3.4 For-Each 循环
  • JDK 1.5 引进了一种新的循环类型,被称为 For-Each 循环或者增强型 for 循环,它能在不使用下标的情况下遍历数组。(点此了解)
  • 示例:foreach 循环遍历数组并打印
    public class Demo01 {
        public static void main(String[] args) {
            // 初始化数组
            int[] array = {10,20,30,40,50,60,70,80,90};
            // foreach循环
            for (int num : array) {
                System.out.println(num);
            }
        }
    }
    
3.5 数组作为方法参数
  • 数组可以作为参数传递给方法。
  • 数组可以作为返回值返回给方法。
  • 示例:找出一个数组的最大值与最小值,并以数组形式返回。
    public class Demo02 {
        public static void main(String[] args) {
            double[] array = new double[100];
            // 为数组赋值随机数
            for (int i = 0; i < array.length; i++) {
                array[i] = Math.random() * 100;
                // 每五个数字换一行
                if (i != 0 && i % 5 == 0){
                    System.out.println();
                }
                System.out.print(array[i]+"t");
            }
            double[] minMax = minMax(array);
            System.out.println("nt数组的最小值为:"+minMax[0]+",最大值为:"+minMax[1]);
        }
    
        // 找出数组中的最大值与最小值
        public static double[] minMax(double[] array) {
            double min = array[0];// 假设数组第 0 个元素为最小值
            double max = array[9];// 假设数组第 9 个元素为最大值
            for (double num : array) {
                if (min > num) {// 找到数组最小值
                    min = num;
                }
                if (max < num) {// 找到数组最大值
                    max = num;
                }
            }
            return new double[]{min,max};
        }
    }
    
四、多维数组

quad 多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组。注:多维数组的每个数组元素的长度可以不一致。

quad 多维数组与一维数组相同,都是通过索引对元素进行访问的。以二维数组为例:array[2][3]即访问 array 数组第 2 行第 3 列的元素。

4.1 初始化 4.1.1 静态初始化
  • 声明数组的同时使用大括号直接对数组赋值。
  • 以二维数组为例:int[][] array = {{1,2,3},{4,5,6},{7,8,9}},此语句声明了一个 3 行 3 列的二维数组。
  • 注:多维数组的每个数组元素的长度可以不一致,例:int[][] array = {{1},{2,3},{4,5,6}};
4.1.2 动态初始化 1. 直接为每一维分配空间
  • 格式:type[][]...[] arrayName = new type[length1][length2]...[lengthN];其中 type 可以为基本数据类型和引用数据类型,length1、length2、… 、lengthN 必须为正整数。
  • 二维数组:type[][] arrayName = new type[rowLength][columnLength];其中 rowLength 表示行长度,columnLength 表示列长度。
  • 示例:int[][] array = new int[3][3];
2. 从最高维开始,分别为每一维分配空间
  • 首先为最高维分配引用空间,也就是为最高维能保存数据的最大长度,然后再为其每个数组元素单独分配空间。
  • 示例:
    public class Demo04 {
        public static void main(String[] args) {
            int[][] numArray = new int[2][];
            numArray[0] = new int[3];
            numArray[0][0] = 1;
            numArray[0][1] = 2;
            numArray[0][2] = 3;
            numArray[1] = new int[]{4,5,6,7,8};
            for (int[] array : numArray) {
                for (int num : array) {
                    System.out.print(num + ",");
                }
                System.out.println();
            }
        }
    }
    
五、Arrays 类
  • 由于数组对象本身并没有什么方法可以供我们调用,但 API 中提供了一个工具类 Arrays 供我们使用,从而可以对数组对象进行一些基本的 *** 作。
  • Arrays 类中的方法都是 static 修饰的静态方法,在使用的时候可以直接使用类名进行调用,而 “不用” 使用对象来调用(注意:是 “不用” 而不是 “不能”)
  • Arrays 类常用方法:(array 表示数组变量)
    1. Arrays.toString(array):返回指定数组 array 内容的字符串表示形式。
    2. Arrays.fill(array,[ int fromIndex, int toIndex,] dataType val):将指定的 dataType 类型的 val 值分配给指定的 array 数组的指定范围的每个元素。注意事项:
      • dataType 要与 array 数组的类型相同。
      • [ int fromIndex, int toIndex,] 为可选。
    3. Arrays.equals​(dataType[] array1,[ int aFromIndex, int aToIndex,] dataType[] array2[, int bFromIndex, int bToIndex]):比较两个数组 array1、array2 在指定范围内是否相等。注意事项:
      • [ int aFromIndex, int aToIndex,] 与 [, int bFromIndex, int bToIndex] 为可选。
    4. Arrays.copyOf(dataType[] original, int newLength):从原数组 original 复制指定长度 newLength 的数组到新的数组对象。
    5. Arrays.sort​(dataType[] array[, int fromIndex, int toIndex]):按升序排列数组的指定范围。注意事项:
      • [, int fromIndex, int toIndex] 为可选。
    6. Arrays.binarySearch​(dataType[] array, int fromIndex, int toIndex, dataType key):使用二分查找算法在给定数组 array 中搜索给定值的对象 key。
      • 数组在调用前必须排序好。
      • 如果查找值 key 包含在数组 array 中,则返回搜索键的索引;否则返回 (-(插入点)-1),插入点是索引键 key 将要插入数组的那一点,即第一个大于该键的元素索引。
六、稀疏数组 6.1 稀疏数组引入
  • 需求:编写五子棋游戏中,有存储棋局退出和继续上一棋局的功能。
  • 分析问题:因为该二维数组的很多值是默认值 0,因此记录了很多没有意义的数据。
  • 解决:稀疏数组。
6.2 稀疏数组介绍
  • 当一个数组中大部分元素为 0,或者为同一值的数组时,可以使用稀疏数组来保存该数组。
  • 稀疏数组的处理方式是:
    • 记录数组一共有几行几列,有多少个不同值。
    • 把具有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模。
  • 如下图:左边是原始数组,右边是稀疏数组。
  • 五子棋游戏的棋盘数组转为稀疏数组:
  • 示例:将五子棋棋盘使用稀疏数组保存。
    public class Demo06 {
        public static void main(String[] args) {
            // 创建一个二维数组 11 * 11。其中,0:没有棋子,1:白棋,2:黑棋
            int[][] array = new int[11][11];
            array[1][2] = 1;
            array[2][3] = 2;
            // 打印原始数组
            printArray(array,"原始数组:");
            // 获取非零元素个数
            int num = nonZero(array);
            // 原始数组转为稀疏数组
            int[][] sparseArray = originalToSparse(array, num);
            printArray(sparseArray,"稀疏数组:");
            // 稀疏数组转为原始数组
            int[][] originalArray = sparseToOriginal(sparseArray);
            printArray(originalArray,"原始数组:");
        }
        // 获取原始数组非零元素个数
        public static int nonZero(int[][] originalArray) {
            int num = 0;
            for (int[] numArray : originalArray) {
                for (int i : numArray) {
                    if (i != 0) {
                        num++;
                    }
                }
            }
            System.out.println("一共有 "+num+" 个有效数字");
            return num;
        }
        // 稀疏数组转换为原始数组
        public static int[][] sparseToOriginal(int[][] sparseArray) {
            int[][] originalArray = new int[sparseArray[0][0]][sparseArray[0][1]];
            for (int i = 1; i < sparseArray.length; i++) {
                originalArray[sparseArray[i][0]][sparseArray[i][1]] = sparseArray[i][2];
            }
            return originalArray;
        }
        // 原始数组转换为稀疏数组
        public static int[][] originalToSparse(int[][] array, int num) {
            int[][] sparseArray = new int[num+1][3];
            int line = 0;
            sparseArray[line] = new int[]{array.length, array.length, num};
            for (int i = 0; i < array.length; i++) {
                for (int j = 0; j < array[i].length; j++) {
                    if (array[i][j] != 0 && line < num) {
                        sparseArray[++line] = new int[]{i,j,array[i][j]};
                    }
                }
            }
            return sparseArray;
        }
        // 打印数组
        public static void printArray(int[][] array, String str) {
            System.out.println(str);
            for (int[] numArray : array) {
                for (int i : numArray) {
                    System.out.print(i+"t");
                }
                System.out.println();
            }
        }
    }
    

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5608315.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-15
下一篇 2022-12-15

发表评论

登录后才能评论

评论列表(0条)

保存