Java语言基础(三)---数组

Java语言基础组成:关键字、标识符、注释、常量和变量、运算符、语句、函数、数组

一. 数组的定义:

  同一种类型数据的集合,其实数组就是一个容器。
  运算时很多数据进行运算,先想到的不是运算,而是要把这些数据临时存储起来,以便于后期的运算。数组就是存储数据的一种方式。
【数组的好处】:数组能自动给存入元素进行编号,编号从0开始,方便操作这些元素。

【数组的格式 1】:   元素类型[ ] 数组名 = new 元素类型[元素个数或数组长度];

  • 【元素类型】: 数组中元素的数据类型

  • 【数组名】: 是数组类型的,数组是单独的数据类型

  • 【new 元素类型[元素个数或数组长度]】:定义了真实存在的数组,能存(数组长度)个元素

  • 【new】: 用于在内存中产生一个容器实体。用来操作很多数据的地方,就用new来完成

  • 【实例】:定义一个可以存储3个整数的容器(具体两种方法定义长度为3的整型数组)

      1. int[ ] x = new int[3];

      2. int x[ ] = new int[3];  // 建议采用第一种

【数组的格式 2】:
(静态存储方式)
  元素类型[ ] 数组名 = new 元素类型[ ]{ 元素1, 元素2, … };

  • 【 [ ] 】: 中括号中不要写长度

  • 【何时使用?】: 当数据内容明确时使用

  • 【静态存储方式】: 通过 { } 的形式,标识出数组中元素的内容。元素内容,个数都体现了,
              称这种方式为静态存储方式。

  • 【实例】:定义一个可以存储3个整数的容器

      1. int[ ] x = new int[ ]{3, 1, 6};

      2. int x[ ] = {3, 1, 6};  // 简化形式


二. 数组的内存分配及特点:

任何一个应用程序在运行时,都要在内存中开辟空间,cpu处理完A程序才会再处理B程序。
Java程序在运行时,需要在内存中分配5个空间:栈内存、堆内存、方法区、本地方法区、寄存器。

【实例 1】 int x = 3 在内存中的分配情况。

基本数据变量在内存中的分配情况

  • 【分析】:

    1. show函数运行完,show中的变量 x 就会在内存中消失。
    2. 如果show函数中有for循环语句:for (int x = 0; x < 5; x++) {}
      那么同样的,for循环运行完,for循环中的变量 x 就会在内存中消失。
  • 【栈的特点】:数据使用完毕,会自动释放,变量会自动释放。

  • 【内存为什么划分出这么多空间,划分这么细?】:

     因为每一片内存空间中的数据处理方式不一样,对于栈而言,数据使用完会自动释放。

【实例 2】 分析在内存中的分配情况。

    int[] x = new int[3];
    x[0] = 59; 


引用变量在内存中的分配情况

  • 【分析】:

    1. 在栈内存中定义了x,凡是局部变量都在栈内存中开辟空间。
      局部变量指 :
        (1)定义在方法中的变量
        (2)定义在方法参数上的变量。
        (3)定义在for循环里的变量等。

    2. new 出来的实体都在堆里边,堆里边存放的就是实体。实体为:数组和对象。

    3. 【赋值】:将地址值赋值给变量x,赋值的不是数组本身,而是数组在内存中的地址。
              数组并没有真正地存放在x 中去,只存放了地址,它在引用数组而已。

    4. 【指向】:变量x 有值了,称为x 指向了这个数组,或x 引用 了这个数组。

【实例 3】 分析在内存中的分配情况。

    int[] x = new int[3]; 
    x = null;  


引用变量在内存中的分配情况

  • 【分析】:

    1. 只有引用数据类型,才能使用null。x = null =>表示 x 不再指向这个数组,而且x 值为空。

    2. new int[3]在堆内存中没有被任何人引用,就会被垃圾回收机制清除。(具体见堆特点3)
  • 【堆的特点】:

    1. 堆内存中的每个实体,都有一个存放位置(内存地址值),内存里都是二进制的地址值,用地址来标识数据存放的位置,那么这个数组在内存中存放的时候,总有一个起始位置,即所谓的数组指向。

    2. 数组一旦被定义,里边的元素都有值,堆内存中的实体用了封装数据的,都有默认初始化值。
      int型数组值:0
      double型数组值:0.0
      float型数组值:0.0f
      boolean型数组值:false
      String型数组值:null
      char型数组值:’\u0000’ (相当于空格)

    3. 【垃圾回收机制】:数组在堆内存中没人使用了,当一个实体在堆内存中没有任何引用所使用它的话,就视它为垃圾,或Java训圾。这个垃圾不会立刻被内存清除掉,而是在不定时的时间内,启动一个叫垃圾回收机制,将数组实体在堆内存中清除。

      C++语言:由程序员手动地调用一个功能将内存中的数据清除。

      Java:程序员不用手动清除,只要这个对象或实体,在堆内存中已经变为垃圾,JVM会自动启动垃圾回收机制,将堆内存中不再使用的实体清除。

    【实例 4】分析在内存中的分配情况。

     int[] x = new int[3]; 
     int[] y = x; 
     y[1] = 89;
     x = null;

/*【堆内存中有无垃圾?】
   => 没有垃圾,x,y引用指向了同一个数组对象,当x的值为空,不再指向数组时,但是y仍指向数组。
*/


引用变量在内存中的分配情况

【实例 5】分析在内存中的分配情况。

     int[] x = new int[3]; 
     int[] y = new int[3]; 
     y[1] = 89;
     x = null;

/**【堆内存中有无垃圾?】
   => 有垃圾。
      只要是new的,内存中就会开辟新的空间,y指向的是新的数组。
      当x = null时,x之前指向的数组,就无人指向,因而变为了垃圾。
*/


引用变量在内存中的分配情况

三. 数组操作常见问题:

【实例 1】:数组角标越界异常(ArrayIndexOutOfBoundsException )

    public static void main(String[] args) {
        int[] arr = {3, 1, 6};
        System.out.println(arr[2]);  //结果为:6
        System.out.println(arr[3]);  //[错误]
    }

【分析】:

  1. 【编译不报错,运行出错】:在Java编译时并不创建实体,在运行时创建数组,Java编译只是检查语法错误。

  2. 【错误提示 ArrayIndexOutOfBoundsException : 3】:

    (1) [3]:数组角标3越界。

    (2) [ArrayIndexOutOfBoundsException]:数组角标越界异常。
       代表操作数组时,访问到了数组中不存在的角标。
       所以在访问数组角标的时候,注意数组角标不能大于数组的长度,因为数组角标是从0开始的。

【实例 2】:空指针异常(ArrayIndexOutOfBoundsException )

    public static void main(String[] args) {
        int[] arr = {3, 1, 6};
        arr = null;
        System.out.println(arr[1]);  //[错误]
    }

【分析】:

  1. 【编译不报错,运行出错】:在Java编译时并不创建实体,在运行时创建数组,Java编译只是检查语法错误。

  2. 【错误提示 NullPointerException】: 空指针异常。
     当没有任何指向,值为null的情况,该引用还在用于操作实体,就会抛出空指针异常。

四. 数组常见操作:

1. 遍历数组

最为常见的获取数组中的元素,通常用遍历,用for语句循环。【注】:角标最大值 = 数组长度 - 1
数组中有一个属性可以直接获取到数组元素个数:数组名称.length

【注】:System.out.println(arr) 代表:把一个数组实体的引用给直接打印了。
    输出结果为[I@62bc184

  1. 【 [ 】:左中括号,表示数组
  2. 【 I 】:数组的元素类型为 int
  3. 【62bc184】:数组的内存存放地址,地址是由哈希算法计算出来的哈希值(十六进制),
            因为十六进制比较短所以采用十六进制。

【实例 1】:求数组和(【累加思想】:变量 + 循环)

    public static void main(String[] args) {
        int[] arr = {3, 1, 6};
        System.out.println("sum = " + getArraySum(arr));

    }

    /**
     * 功能:求出数组的元素和
     * @param arr 数组
     * @return 数组元素和
     */
    public static int getArraySum(int[] arr)
    {
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
            sum += arr[i];
        }
        return sum;
    }

【实例 2】:定义一个功能,用于打印数组中的元素,元素间用逗号隔开。

    /**
     * 功能:用于打印数组中的元素,元素间用逗号隔开
     * @param arr 数组
     */
    public static void printArray(int[] arr)
    {
        for (int i = 0; i < arr.length; i++)
        {
            if (i != arr.length - 1) //元素间逗号隔开
            {
                System.out.print(arr[i] + ",");
            }
            else
            {
                System.out.println(arr[i]);
            }
        }
    }

【实例 3】:给定一个数组{5,1,6,4,2,8,9} 获取数组中的最大值,以及最小值。(只适用于数值型数组)

    /**
     * 方法一:求max
     * 1. 定义变量max,初始化为数组中仁义一个元素值即可,max = arr[0]
     * 2. 通过循环语句,对数组进行遍历
     * 3. 在变量中定义判断条件,如果遍历到的元素比变量中的元素大,就赋值给变量。
     * @param arr 数组
     * @return 最大值
     */
    public static int getMax(int[] arr)
    {
        int max = arr[0];
        for (int i=1; i<arr.length; i++)
        {
            if(max < arr[i])
                max = arr[i];

        }

        return max;
    }


    /**
     * 方法二:求max
     * 1. 定义变量max,初始化为数组中的任意一个角标,max = 0
     * 2. 通过循环语句,对数组进行遍历
     * 3. 在变量中定义判断条件,如果遍历到的元素比arr[max]中的元素大,就将元素角标赋值给变量。
     * @param arr 数组
     * @return 最大值
     */
    /*public static int getMax(int[] arr)
    {
        int max = 0;
        for (int i = 1; i < arr.length; i++)
        {
            if(arr[max] < arr[i])
                max = i;
        }
        return arr[max];
    }*/

    //获取double类型数组的最大值,因为功能一致,所以定义相同函数名称,以重载方式存在。
    public static double getMax(double[] arr)
    {
    }

    /**
     * 求min
     * @param arr 数组
     * @return 最小值
     */
    public static int getMin(int[] arr)
    {
        int min = arr[0];
        for (int i=1; i<arr.length; i++)
        {
            if(min > arr[i])
                min = arr[i];

        }

        return min;
    }

2. 数组排序

【排序的方法】:

  1. 冒泡排序 :相邻两个元素进行排序,如果符合条件则换位。
          特点:内循环结束一次,最值出现在最后位。

  2. 选择排序:选择固定位置的值,不断地和其他元素进行比较,符合条件则换位,接着拿这个位置上的值进行比较。
         特点:内循环结束一次,最值出现在头角标位置上。

  3. 插入排序:需要排序的数组越有序,插入排序的效率越高。

  4. 希尔排序(是最快的排序,三层循环加上位运算):
          将需要排序的数组分割成小的子数组,对这个子数组进行插入排序,排序后越来越接近有序的数组。

  5. 快速排序

  6. 归并排序

  7. 工具类Arrays:
      在Java中, 已经定义好了一种排序方式,是使用到了专门操作数组的工具类Arrays。
      Arrays有一个静态方法sort可以对数组进行排序。例如:Arrays.sort(arr);

【实例】 对给定数组进行排序。{5,1,6,4,2,8,9}

(1)方法一:选择排序

选择排序

  • 【选择排序】:选择固定位置的值不断和别人进行比较,交换位置后,依旧拿这个位子的值与别人比较。

  • 【选择排序的特点】:内循环结束一次,最值出现在头角标位置上,前面逐级进行排序

【实例】:代码体现

    public static void main(String[] args) {
        int[] arr = {5,1,6,4,2,8,9};
        System.out.println("-------------排序前-------------");
        printArray(arr);
        selectSort(arr); //选择排序
        System.out.println("-------------排序后-------------");
        printArray(arr);
    }
    /**
     * 选择排序
     * @param arr 数组
     */
    public static void selectSort(int[] arr)
    {
        for (int i = 0; i < arr.length - 1; i++) {  //不需要遍历最后一个角标,所以arr.length - 1

            for(int j = i + 1; j < arr.length; j++) //每个元素与后面进行比较,所以i + 1
            {
                if(arr[i] > arr[j])
                {
                    swap(arr, i, j); //两数交换
                }
            }
        }
    }

    /**
     * 交换数组中的两个元素
     * @param arr 数组
     * @param i 数组角标i
     * @param j 数组角标j
     */
    public static void swap(int[] arr, int i, int j)
    {
        arr[i] = arr[i] ^ arr[j];
        arr[j] = arr[i] ^ arr[j];
        arr[i] = arr[i] ^ arr[j];
    }

    /**
     * 打印数组
     * @param arr 数组
     */
    public static void printArray(int[] arr)
    {
        for (int i = 0; i < arr.length; i++) {
            if( i != arr.length -1)
            {
                System.out.print(arr[i] + ", ");
            }
            else
            {
                System.out.println(arr[i]);
            }
        }
    }

(2)方法二:冒泡排序

冒泡排序

  • 【冒泡排序】:相邻的两个元素进行排序,如果符合条件换位。

  • 【冒泡排序的特点】:

    1. 每次循环都是从0角标开始的。

    2. 第一圈最值出现在最后位。

    3. 第二次比较的特点:参与比较元素的长度 -1,逐渐减小。

【实例 1】:代码体现

    public static void main(String[] args) {
        int[] arr = {5,1,6,4,2,8,9};
        System.out.println("-------------排序前-------------");
        printArray(arr);
        bubbleSort(arr); //冒泡排序
        System.out.println("-------------排序后-------------");
        printArray(arr);
    }

    /**
     * 冒泡排序
     * @param arr 数组
     */
    public static void bubbleSort(int[] arr)
    {
        for (int i = 0; i < arr.length - 1; i++) { //共循环比较arr.length - 1圈

            for (int j = 0; j < arr.length - i -1; j++) { //-i:让每次比较的元素减少; -1:避免角标越界
                if(arr[j] > arr[j + 1])
                {
                    swap(arr, j, j + 1); //两数交换,但是直接换位置,性能低,一圈中要换好几次
                }
            }
        }
    }

    /**
     * 交换数组中的两个元素
     * @param arr 数组
     * @param i 数组角标i
     * @param j 数组角标j
     */
    public static void swap(int[] arr, int i, int j)
    {
        arr[i] = arr[i] ^ arr[j];
        arr[j] = arr[i] ^ arr[j];
        arr[i] = arr[i] ^ arr[j];
    }

    /**
     * 打印数组
     * @param arr 数组
     */
    public static void printArray(int[] arr)
    {
        for (int i = 0; i < arr.length; i++) {
            if( i != arr.length -1)
            {
                System.out.print(arr[i] + ", ");
            }
            else
            {
                System.out.println(arr[i]);
            }
        }
    }

【实例 2】:冒泡排序的更优解(每一圈取出最值的角标,与最后的角标交换位置)

 如果两个数需要换位置的话,先不要置换它们的位置,先把它们需要换位置的角标及元素记录下来。
 在栈内存中,定义两个变量,临时记录下来,全都比较完后,取最终需要换位置的值就可以了。
 把堆内存中频繁地换位置,转移到栈内存中。

    public static void main(String[] args) {
        int[] arr = {5,1,6,4,2,8,9};
        System.out.println("-------------排序前-------------");
        printArray(arr);
        bubbleSort(arr); //冒泡排序
        System.out.println("-------------排序后-------------");
        printArray(arr);
    }

    /**
     * 冒泡排序
     * @param arr 数组
     */
    public static void bubbleSort(int[] arr)
    {
        for (int i = 0; i < arr.length - 1; i++) {

            int j = 0, max = 0; //max 记录最大值的角标

            for (j = 1; j < arr.length - i; j++) {
                if(arr[j] > arr[max])
                {
                    max = j;
                }
            }
            if(j-1 != max) //如果max 角标不等于最后一个角标,两数交换
            {
                swap(arr, j-1, max); //两数交换
            }
        }
    }

    /**
     * 交换数组中的两个元素
     * @param arr 数组
     * @param i 数组角标i
     * @param j 数组角标j
     */
    public static void swap(int[] arr, int i, int j)
    {
        arr[i] = arr[i] ^ arr[j];
        arr[j] = arr[i] ^ arr[j];
        arr[i] = arr[i] ^ arr[j];
    }

    /**
     * 打印数组
     * @param arr 数组
     */
    public static void printArray(int[] arr)
    {
        for (int i = 0; i < arr.length; i++) {
            if( i != arr.length -1)
            {
                System.out.print(arr[i] + ", ");
            }
            else
            {
                System.out.println(arr[i]);
            }
        }
    }

(3)方法三:直接插入排序

直接插入排序

  • 【插入排序】:将一个元素插入到已经排好序的数组中去,从而得到一个新的数组长度 + 1 的有序数组。

  • 【插入排序的原理】:

    1. 假设数组为一个有序数组。

    2. 每次判断数组元素是否大于前一个数,如果小于的话,就往前遍历数组,将大于这个数的元素往后移,将这个数放入到具体位置,使数组依然为有序数组。

【实例】:代码体现(针对 insterSort 方法)

    /**
     * 直接插入排序
     * @param arr 数组
     */
    public static void insterSort(int[] arr)
    {
        for (int i = 1; i < arr.length; i++) { //由角标1开始遍历数组
            if(arr[i] < arr[i-1]) //判断数组元素是否大于前一个数
            {
                int temp = arr[i], j;
                for (j = i - 1; j >= 0 && arr[j] > temp; j--) { //数组往后移动
                    arr[j + 1] = arr[j];
                }
                arr[j + 1] = temp;
            }
        }
    }

(4)方法四:希尔排序

希尔排序

  • 【希尔排序】:把数组进行分组,分割成若干个子序列,然后对子序列进行基本的插入排序。

  • 【希尔排序的原理】:

    1. 普通的插入排序:判断间隔间隔为1
    2. 希尔排序:判断间隔为space,并且间隔不断缩小(除2操作)直到为0。

【实例 】:代码体现

    /**
     * 直接插入排序 + 希尔排序 + space取整
     * @param arr 数组
     */
    public static void shellSort(int[] arr)
    {
        int space = arr.length;
        do
        {
            space >>= 1; // space = space/2;

            for (int i = space; i < arr.length; i++) {  //在直接排序的基础上,将间隔1,改为space
                if(arr[i] < arr[i-space])
                {
                    int temp = arr[i], j;
                    for (j = i - space; j >= 0 && arr[j] > temp; j -= space) {
                        arr[j + space] = arr[j];
                    }
                    arr[j + space] = temp;
                }
            }

        }while(space > 0);
    }

3. 查找数组

数组的查找操作:在遍历中进行判断。

【查找数组的方法】:

  1. 简单查找:直接遍历数组进行匹配

  2. 折半查找:折中找中间值,提高效率,但必须要保证该数组是有序的数组。

【实例】 定义功能,获取key第一次出现在数组中的位置,如果返回是-1,那么代表该key在数组中不存在
 (因为数组下标不会存在-1)

  • (1) 方法一:从0角标遍历数组,进行查找
    /**
     * 获取key第一次出现在数组中的位置
     * @param arr 数组
     * @param key 匹配的数据
     * @return 数组角标或-1,如果为-1,没有找到key
     */
    public static int getIndex(int[] arr, int key)
    {
        for (int i = 0; i < arr.length; i++) {
            if(key == arr[i])
            {
                return i;
            }
        }
        return -1;
    }
  • (2) 方法二:折半查找

折半查找

    /**
     * 获取key第一次出现在数组中的位置
     * @param arr 数组
     * @param key 匹配的数
     * @return 数组角标或 -1
     */
    public static int halfSearch(int[] arr, int key)
    {
        int min = 0, max = arr.length - 1, mid;
        while(min <= max) //当min>max, 循环结束
        {
            mid = (min + max) >> 1; //获得mid
            if(key > arr[mid])
            {
                min = mid + 1; 
            }
            else if(key < arr[mid])
            {
                max = mid - 1;
            }
            else
            {
                return mid;
            }
        }
        return -1;
    }

4. 插入元素

【实例】 有个有序的数组,想要将一个元素插入到该数组中,还要保证该数组是有序的。

【思路】:通过折半的形式去查找这个数,在数组中的位置,如果这个数存在,在这个位置上把这个数插入,如果不存在,返回最小角标的值,就可以得到要插入的位置。

插入元素

    /**
     * 折半查找,获取插入元素的角标
     * @param arr 数组
     * @param num 要插入的元素
     * @return 要插入元素的角标
     */
    public static int halfSearch(int[] arr, int num)
    {
        int min = 0, max = arr.length - 1, mid;
        while(min <= max)
        {
            mid = (min + max) >> 1;
            if(num > arr[mid])
            {
                min = mid + 1;
            }
            else if(num < arr[mid])
            {
                max = mid - 1;
            }
            else
            {
                return mid;
            }
        }
        return min;
    }

    /**
     * 将元素插入的相应的位置上,获得新数组
     * @param arr 数组
     * @param index 要插入的角标
     * @param num 元素值
     * @return 新数组
     */
    public static int[] getNewArray(int[] arr, int index, int num)
    {
        int[] rtnArr = new int[arr.length + 1];
        for (int i = 0; i < index; i++) {
            rtnArr[i] = arr[i];
        }
        rtnArr[index] = num;  //插入元素到指定位置
        for (int i = index; i < arr.length; i++) {
            rtnArr[i + 1] = arr[i];
        }
        return rtnArr;
    }

5. 进制转换

(1)十进制转换二进制

    /**
     * 十进制转换二进制
     * @param num 十进制数
     * @return 二进制(以字符串形式返回)
     */
    public static String toBin(int num)
    {
        StringBuilder sb = new StringBuilder();
        while(num > 0)  //有局限,负数无法求出
        {
            sb.append(num % 2 );
            num >>= 1;
        }
        return sb.reverse().toString();
    }

【查表法】:将所有的元素临时存储起来,建立对应关系,每一次&运算后的值作为索引去查建立好的表,就可以找到对应的元素(不用强制转换了)

【利用查表法,更改上面的十进制转换】

    /**
     * 进制表
     */
    final static char[] digits = {
        '0' , '1' , '2' , '3' , '4' , '5' ,
        '6' , '7' , '8' , '9' , 'a' , 'b' ,
        'c' , 'd' , 'e' , 'f' 
    };

    /**
     * 十进制转换二进制
     * @param num 十进制数
     * @return 二进制(以字符串形式返回)
     */
    public static String toBin(int num)
    {
        StringBuilder sb = new StringBuilder();
        while(num != 0)
        {
            int temp = num & 1;
            sb.append(digits[temp]); //利用查表法,直接获取对应值
            num >>>= 1;
        }
        return sb.reverse().toString();
    }

(2)十进制转换十六进制

    /**
     * 进制表
     */
    final static char[] digits = {
        '0' , '1' , '2' , '3' , '4' , '5' ,
        '6' , '7' , '8' , '9' , 'a' , 'b' ,
        'c' , 'd' , 'e' , 'f' 
    };
    /**
     * 十进制转换二进制
     * @param num 十进制数
     * @return 二进制(以字符串形式返回)
     */
    public static String toHex(int num)
    {
        StringBuilder sb = new StringBuilder();
        while(num != 0)
        {
            int temp = num & 15;
            /*if(temp > 9)
            {
                sb.append((char)(temp-10 + 'a'));
            }
            else
            {
                sb.append(temp);
            }*/
            sb.append(digits[temp]);
            num >>>= 4;
        }
        return sb.reverse().toString();
    }

(3)十进制转换各种进制(升级版)


    /**
     * 进制表
     */
    final static char[] digits = {
        '0' , '1' , '2' , '3' , '4' , '5' ,
        '6' , '7' , '8' , '9' , 'a' , 'b' ,
        'c' , 'd' , 'e' , 'f' 
    };

    public static void main(String[] args) {
        System.out.println(toBin(0));
        System.out.println(toHex(-60));
    }
    /**
     * 十进制转各种进制数
     * @param num 十进制数
     * @param base &运算的基数
     * @param offset >>>位移多少位
     * @return
     */
    public static String trans(int num, int base, int offset)
    {
        if(num == 0) // 不然当0的时候,没有值
        {
            return "0";
        }
        StringBuilder sb = new StringBuilder();
        while(num != 0)
        {
            int temp = num & base;
            sb.append(digits[temp]);
            num >>>= offset;
        }
        return sb.reverse().toString();
    }

    /**
     * 十进制转换二进制
     * @param num 十进制数
     * @return 二进制(以字符串形式返回)
     */
    public static String toBin(int num)
    {
        return trans(num, 1, 1);
    }

    /**
     * 十进制转换十六进制
     * @param num 十进制数
     * @return 十六进制(以字符串形式返回)
     */
    public static String toHex(int num)
    {
        return trans(num, 15, 4);
    }

    /**
     * 十进制转换八进制
     * @param num 十进制数
     * @return 八进制(以字符串形式返回)
     */
    public static String toOctal(int num)
    {
        return trans(num, 7, 3);
    }

五. 二维数组:

数组中的数组:往数组中存放数组,把数组作为元素存入另一个数组中。

1. 二维数组的定义:

【一维数组】:   int[ ] arr = new int[3];

【二维数组】:
 【数组的格式 1】

  int[ ] arr = new int[3][4];

  • 【内容】: 定义了名称为arr的二维数组,二维数组中有3个一维数组,每个一维数组中有4个元素。

  • 【new int[3][4]】:

      1. [3]:表示二维数组的长度。

      2. [4]:表示二维数组中一维数组的长度。
 【数组的格式 2】

  int[ ] arr = new int[3][ ];

  • 【内容】: 定义了名称为arr的二维数组,二维数组中有3个一维数组,但没有指定一维数组的元素。

  • 【new int[3][ ]】:

      1. [3]:表示二维数组的长度。(一定要写)

      2. [ ]:表示二维数组中一维数组没有指定。即 arr[0] = null;

 【数组的格式 3】(静态存储方式)

  int[ ] arr = { {3, 5, 7}, {2, 3, 5}, {6, 1, 8, 2} };

  • 数据之间有关系,分在一组中,产生二维数组。

【一维数组 与 二维数组的小知识】:

  1. 一维数组:int[ ] x = int x[ ]

  2. 二维数组:int[ ][ ] x = int x[ ][ ] = int[ ] x[ ]

    【实例】int[ ] x, y[ ];  =>  int[ ] x, int[ ] y[ ];

       1. [ ] 定义在类型中,是随类型走的,而类型的[ ],变量都有效
       2. [ ] 定义在变量后,是随着变量走的,只有单个变量有效。

       (1)x[0] = y    [错误]
       (2)y[0] = x    [正确]
       (3)y[0][0] = x   [错误]
       (4)x[0][0] = y   [错误]
       (5)y[0][0] = x[0] [正确]
       (6)x = y      [错误]


2. 二维数组的内存分配:

  • (1)【数组的格式 1】 的内存分配


二维数组的内存分配

【实例】打印二维数组地址值

        int[][] arr = new int[3][4];
        System.out.println(arr);  //[[I@26a2bd15
        System.out.println(arr[0]); //[I@62bc184

        /*
        二维数组的首地址:两个左中括号
        一维数组的首地址:一个左中括号
        */
  • (2)【数组的格式 2】 的内存分配(不规则数组)


二维数组的内存分配

【分析】:

  1. int[ ][ ] arr = new int[3][ ];

    这个二维数组中的一维数组没有初始化,用的是默认初始化,而数组是引用数据类型,所以初始化值都为空,也就是这3个一维数组变量(e.g. arr[0])没有任何的小数组指向。

  2. arr[0] = new int[3];

    对二维数组中每一个小数组进行手动初始化。初始化后,把数组地址赋值给arr[0]。

【实例】打印二维数组地址值

        int[][] arr = new int[3][];
        System.out.println(arr);  //[[I@26a2bd15
        System.out.println(arr[0]); //null (一维数组没有指定)
        arr[0] = new int[3];
        arr[1] = new int[1];
        arr[2] = new int[2];
        arr[0][2] = 90;
        arr[1][1] = 89;
        arr[2][2] = 78;
        System.out.println(arr.length); //结果为:3
        System.out.println(arr[0].length); //结果为:3  打印二维数组中第一个一维数组的长度
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值