第4章 数组

4.1 数组概念

4.1.1 数组的概念

数组概念: 数组就是用于存储数据的长度固定的容器,保证多个数据的数据类型要一致。

数组的定义:

所谓数组(array),就是相同数据类型的元素按一定顺序排列的集合,就是把有限个类型相同的变量用一个名字命名,以便统一管理他们,然后用编号区分他们,这个名字称为数组名,编号称为下标或索引(index)。组成数组的各个变量称为数组的元素(element)。数组中元素的个数称为数组的长度(length)。

4.1.2 数组的分类

1、按照维度分:

  • 一维数组:存储一组数据

  • 二维数组:存储多组数据,相当于二维表,一行代表一组数据,这是这里的二维表每一行长度不要求一样。

2、按照元素类型分:

  • 基本数据类型的元素:存储数据值

  • 引用数据类型的元素:存储对象(本质上存储对象的首地址)(这个在面向对象部分讲解)

注意:无论数组的元素是基本数据类型还是引用数据类型,数组本身都是引用数据类型。

4.2 一维数组的声明与使用

4.2.1 一维数组的声明

一维数组的声明/定义格式:

//推荐
元素的数据类型[ ]  数组名;

//不推荐
元素的数据类型   数组名[ ];

数组的声明,就是要确定:

(1)数组的维度:在Java中数组的标点符号是[ ],[ ]表示一维,[ ][ ]表示二维

(2)数组的元素类型:即创建的数组容器可以存储什么数据类型的数据。元素的类型可以是任意的Java的数据类型。例如:int, String等

(3)数组名:就是代表某个数组的标识符,数组名其实也是变量名,按照变量的命名规范来命名。数组名是个引用数据类型的变量,因为它代表一组数据。

package com.huohua.day0408.code;

public class ArrayCase2 {
    public static void main(String[] args) {
        //数组的声明
        int ageArr1[];
        //推荐使用下面这种
        //存储一组整形的数据
        int[] ageArr2;
        //存储一组浮点型的数据
        float[] score;
        //存储一组字符型数据
        char[] hobby;
        //要使用之前你必须要初始化
        //System.out.println(ageArr1);
    }
}

4.2.2 一维数组的静态初始化

  • 什么是初始化?

    • 初始化就是确定数组元素的总个数(即数组的长度)和元素的值

  • 什么是静态初始化?

    • 静态初始化就是用静态数据(编译时已知)为数组初始化。此时数组的长度由静态数据的个数决定。

  • 一维数组静态初始化格式1:

数据类型[ ] 数组名 = {元素1,元素2,元素3...};//必须在一个语句中完成,不能分开两个语句写

  •  一维数组静态初始化格式2:

数据类型[ ] 数组名 = new 数据类型[ ]{元素1,元素2,元素3...};

数据类型[ ] 数组名;
数组名 = new 数据类型[ ]{元素1,元素2,元素3...};

 例如:

package com.huohua.day0408.code;

public class ArrayCase3 {
    public static void main(String[] args) {
        //声明 静态初始化
        //第一种
//        int[] ageArr = {1, 2, 3, 4, 5};
//        int[] ageArr1;//不能先声明再赋值
//        ageArr1 = {1,2,3,4,5};
//        float[] score = {95f,45,96f,87};
//        char[] charVar = {'a','b','c',35};


        //第二种 静态数据初始化
        //引用数据类型
//        int[] ageArr = new int[]{1, 2, 3, 4, 5};
        float[] score = new float[]{95f, 45, 96f, 87};
        int[] ageArr;//可以先声明再赋值
        ageArr =new int[]{1,2};
    }
}

4.2.3 一维数组的使用

  • 如何获取数组的元素总个数,即数组的长度

数组的长度属性: 每个数组都具有长度,而且是固定的,Java中赋予了数组的一个属性,可以获取到数组的长度,语句为:数组名.length ,属性length的执行结果是数组的长度,int类型结果。

数组名.length

  • 如何表示数组中的一个元素?

每一个存储到数组的元素,都会自动的拥有一个编号,从0开始,这个自动编号称为数组索引(index)或下标,可以通过数组的索引/下标访问到数组中的元素。

数组名[ 索引/下标 ]

  • 数组的下标范围?

Java中数组的下标从[0]开始,下标范围是[0, 数组的长度-1],即[0, 数组名.length-1]

  • 一维数组的使用

package com.huohua.day0408.code;

public class ArrayCase4 {
    public static void main(String[] args) {
//        数组的长度
        int[] ageArr = {1,2,3,4,5};
//        数组的长度
        System.out.println(ageArr.length);
//        下标 从0 开始 [index]
        System.out.println(ageArr[0]);
        System.out.println(ageArr[4]);
//        蓝色的字是代码的错误  下标越界超出数组的范围
//        (ArrayCase4.java:13)
        System.out.println(ageArr[5]);
    }
}

4.2.4 一维数组遍历

数组遍历: 就是将数组中的每个元素分别获取出来,就是遍历。遍历也是数组操作中的基石。for循环与数组的遍历是绝配。

package com.huohua.day0408.code;

public class ArrayCase5 {
    public static void main(String[] args) {
        float[] score = {95f, 45, 96f, 87};
        //0 ~ score.length-1
        for (int i = 0; i < score.length; i++) {
            System.out.println(score[i]);
        }
        char[] charVar = {'a','b','c',35};
        for (int i = 0; i <charVar.length ; i++) {
            System.out.println(charVar[i]);
        }
        boolean[] bool = {true,false,false,true};
        for (int i = 0; i <bool.length ; i++) {
            System.out.println(bool[i]);
        }
        int[] intNum = {1,2,3,4,5};
        for (int i = 0; i <intNum.length ; i++) {
            System.out.println(intNum[i]);
        }
    }
}

4.2.5 一维数组的动态初始化

  • 什么是动态初始化?

动态初始化就是先确定元素的个数(即数组的长度),而元素此时只是默认值,并不是真正的数据。元素真正的数据需要后续单独一个一个赋值。

  • 格式:

 数组存储的元素的数据类型[ ] 数组名 = new 数组存储的元素的数据类型[ 长度 ];

  或

 数组存储的数据类型[ ] 数组名;
 数组名字 = new 数组存储的数据类型[ 长度 ];

  • new:关键字,创建数组使用的关键字。因为数组本身是引用数据类型,所以要用new创建数组对象。

  • [ 长度 ]:数组的长度,表示数组容器中可以存储多少个元素。

  • 注意:数组有定长特性,长度一旦指定,不可更改。和水杯道理相同,买了一个2升的水杯,总容量就是2升是固定的。

package com.huohua.day0408.code;

import java.util.Scanner;

public class ArrayCase6 {
    public static void main(String[] args) {
        //动态初始化时,已经给了初始值
        int[] arr = new int[5];
//        for (int i = 0; i < arr.length; i++) {
//            System.out.println(arr[i]);
//        }
//        for (int i = 0; i < arr.length; i++) {
//            arr[i] = 2 * i;
//            System.out.println(arr[i]);
//        }
        Scanner scan = new Scanner(System.in);
        for (int i = 0; i < arr.length; i++) {
            System.out.println("请输入第" + (i + 1) + "个值");
            arr[i] = scan.nextInt();
        }
        String outArr = "[";
        for (int i = 0; i < arr.length; i++) {
            if (i == 0) {
                outArr += arr[i];
            } else {
                outArr += "," + arr[i];
            }
        }
        outArr += "]";
        System.out.println(outArr);
    }
}

4.2.6 数组元素的默认值

当我们使用动态初始化方式创建数组时,元素只是默认值。

4.3 一维数组的内存分析

4.3.1 内存概述

内存是计算机中重要的部件之一,它是与CPU进行沟通的桥梁。其作用是用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器交换的数据。只要计算机在运行中,CPU就会把需要运算的数据调到内存中进行运算,当运算完成后CPU再将结果传送出来。我们编写的程序是存放在硬盘中的,在硬盘中的程序是不会运行的,必须放进内存中才能运行,运行完毕后会清空内存。

Java虚拟机要运行程序,必须要对内存进行空间的分配和管理。

4.3.2 Java虚拟机的内存划分

为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。

区域名称作用
程序计数器程序计数器是CPU中的寄存器,它包含每一个线程下一条要执行的指令的地址
本地方法栈当程序中调用了native的本地方法时,本地方法执行期间的内存区域
方法区存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
堆内存存储对象(包括数组对象),new来创建的,都存储在堆内存。
虚拟机栈用于存储正在执行的每个Java方法的局部变量表等。局部变量表存放了编译期可知长度的各种基本数据类型、对象引用,方法执行完,自动释放。

4.4.3 一维数组在内存中的存储

1、一个一维数组内存图

​
​
package com.huohua.day0408.code;

public class ArrayCase7 {
    public static void main(String[] args) {
        int[] arr1=new int[5];
        System.out.println(arr1);//[I@1b6d3586
    }
}

​

​

思考:打印arr为什么是[I@1b6d3586,它是数组的地址吗?

答:它不是数组的地址。

问?不是说arr中存储的是数组对象的首地址吗?

答:arr中存储的是数组的首地址,但是因为数组是引用数据类型,打印arr时,会自动调用arr数组对象的toString()方法,该方法默认实现的是对象类型名@该对象的hashCode()值的十六进制值。

问?对象的hashCode值是否就是对象内存地址?

答:不一定,因为这个和不同品牌的JVM产品的具体实现有关。例如:Oracle的OpenJDK中给出了5种实现,其中有一种是直接返回对象的内存地址,但是OpenJDK默认没有选择这种方式。

2、数组下标为什么是0开始

因为第一个元素距离数组首地址间隔0个单元格。

3、两个一维数组内存图

两个数组独立

​
package com.huohua.day0408.code;

public class ArrayCase7 {
    public static void main(String[] args) {
        int[] arr1=new int[5];
        char[] arr2 = new char[5];
        boolean[] arr3 = new boolean[5];
        float[] arr4 = new float[5];
        String[] arr5 = new String[5];
        int[] arr6 = new int[10];
        System.out.println(arr1);//[I@1b6d3586
        System.out.println(arr2);//           
        System.out.println(arr3);//[Z@4554617c
        System.out.println(arr4);//[F@74a14482
        System.out.println(arr5);//[Ljava.lang.String;@1540e19d
        System.out.println(arr6);//[I@677327b6
    }
}

​

4、两个变量指向一个一维数组

两个数组变量本质上代表同一个数组。

public static void main(String[] args) {
    // 定义数组,存储3个元素
    int[] arr = new int[3];
    //数组索引进行赋值
    arr[0] = 5;
    arr[1] = 6;
    arr[2] = 7;
    //输出3个索引上的元素值
    System.out.println(arr[0]);
    System.out.println(arr[1]);
    System.out.println(arr[2]);
    //定义数组变量arr2,将arr的地址赋值给arr2
    int[] arr2 = arr;
    arr2[1] = 9;
    System.out.println(arr[1]);
}

4.4 一维数组常见算法

4.4.1 数组统计:求和,求均值,统计偶数个数等。

package com.huohua.day0408.code;

public class ArrayCase15 {
    public static void main(String[] args) {
        //求总和以及均值、总乘积、统计偶数个数
        int[] arr = {1, 2, 3, 4, 5};
        //求总和
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
            sum += arr[i];
        }
        System.out.println("总和:"+sum);
        //均值
        System.out.println("均值:"+(double)sum/arr.length);
    }
}
package com.huohua.day0408.code;

public class ArrayCase16 {
    public static void main(String[] args) {
        //求总和以及均值、总乘积、统计偶数个数
        int[] arr = {1, 2, 3, 4, 5};
        //总乘积
        int num=1;
        for (int i = 0; i <arr.length ; i++) {
            num *=arr[i];
        }
        System.out.println("总乘积:"+num);

    }
}
package com.huohua.day0408.code;

public class ArrayCase17 {
    public static void main(String[] args) {
        //求总和以及均值、总乘积、统计偶数个数
        int[] arr = {1, 2, 3, 4, 5, 6, 7, 8};
        //偶数个数
        int count = 0;
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] % 2 == 0) {
                count++;
            }
        }
        System.out.println("偶数个数:" + count);
    }
}

4.4.2 数组找最值

1、找最大值/最小值

思路:

(1)先假设第一个元素最大/最小

(2)然后用max/min与后面的元素一一比较

package com.huohua.day0408.code;

public class ArrayCase11 {
    public static void main(String[] args) {
        int[] arr = new int[]{14, 26, 32, 13, 25};
        //求最大值和最小值
        int max = arr[0];
        int min = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (max < arr[i]) {
                max = arr[i];
            }
            if (min > arr[i]) {
                min = arr[i];
            }
        }
        System.out.println("最大值"+max);
        System.out.println("最小值"+min);
    }
}

2、找最值及其第一次出现的下标

思路:

(1)先假设第一个元素最大/最小

(2)用max/min变量表示最大/小值,用max/min与后面的元素一一比较

(3)用index时刻记录目前比对的最大/小的下标

package com.huohua.day0408.code;

public class ArrayCase13 {
    public static void main(String[] args) {
        int[] arr = new int[]{14, 26, 32, 13, 25};
        //求最大值和最小值
        int maxIndex = 0;
        int minIndex = 0;
        for (int i = 1; i < arr.length; i++) {
            if (arr[maxIndex] < arr[i]) {
                maxIndex = i;
            }
            if (arr[minIndex] > arr[i]) {
                minIndex = i;
            }
        }
        System.out.println("最大值下标"+maxIndex);
        System.out.println("最小值下标"+minIndex);
    }
}

4.4.3 数组的元素查找

1、顺序查找

顺序查找:挨个查看

要求:对数组元素的顺序没要求

package com.huohua.day0408.code;

import java.util.Scanner;

public class ArrayCaseOrderSeach19 {
    public static void main(String[] args) {
        //顺序查找
        int[] arr = {3, 6, 7, 1, 2, 10, 21, 4};
        Scanner scan = new Scanner(System.in);
        System.out.println("请输入你要找的值");
        int value = scan.nextInt();
        int index = -1;
        for (int i = 0; i < arr.length; i++) {
            if (value == arr[i]) {
                index = i;
                break;
            }
        }
        if (index == -1) {
            System.out.println(value + "在数组中不存在");
        } else {
            System.out.println(value + "第一次出现的索引下标是:" + index);
            System.out.println("数组的总长度位" + arr.length);
        }
    }
}

2、二分查找

package com.huohua.day0408.code;

import java.util.Scanner;

public class ArrayCaseBinatySeach18 {
    public static void main(String[] args) {
        //二分查找(折半查找)  必须是有序数组
        //①
        int[] arr = {1, 2, 3, 4, 6, 7, 10, 21};
        Scanner scan = new Scanner(System.in);
        System.out.println("请输入你要找的值");
        //②
        int value = scan.nextInt();
        //③设置起始的下标位
        int left = 0;
        //④结束的下标位
        int right = arr.length - 1;
        //⑤目标元素的index值
        int index = -1;
        while (left <= right) {
            //⑥
            int mid = (left + right) / 2;
            //判断比较
            if (arr[mid] == value) {
                index = mid;
                break;
            }
            if (arr[mid] > value) {
                right = mid - 1;
            }
            if (arr[mid] < value) {
                left = mid + 1;
            }
        }
        if (index == -1) {
            System.out.println("数组中不存在你要找的值");
        } else {
            System.out.println("你要找的值" + value + "的索引下标为" + index);
        }
    }
}

4.4.4 数组元素排序

1、排序算法概述

数组的排序算法很多,实现方式各不相同,时间复杂度、空间复杂度、稳定性也各不相同:

2、直接选择排序

package com.huohua.day0408.code;

/*
选择排序
从小到大
目标元素设定位置,按照目标的本来元素和目标后面的元素进行比较,直到尾部
当比较一轮后,记录最小值的索引与目标位置的元素进行交换
*/

import java.util.Arrays;

public class SelectOrder20 {
    public static void main(String[] args) {
        int[] arr = {6, 3, 12, 4, 8};
        //按照循环设定目标位置
        for (int i = 0; i < arr.length; i++) {
            //目标后面的元素进行一一比对
            int min = arr[i];
            int index = i;
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[j] < min) {
                    min = arr[j];
                    index = j;
                }
            }
            //交换数值
            if (index != i) {
                //中间变量进行交换
                int temp = arr[i];
                arr[i] = arr[index];
                arr[index] = temp;
            }
        }
        System.out.println(Arrays.toString(arr));
    }
}

3、冒泡排序

Java中的经典算法之冒泡排序(Bubble Sort)

原理:比较两个相邻的元素,将值大的元素交换至右端。

思路:依次比较相邻的两个数,将小数放到前面,大数放到后面。

即第一趟,首先比较第1个和第2个元素,将小数放到前面,大数放到后面。

然后比较第2个和第3个元素,将小数放到前面,大数放到后面。

如此继续,直到比较最后两个数,将小数放到前面,大数放到后面。

重复第一趟步骤,直至全部排序完成。

​
package com.huohua.day0408.code;

/*
冒泡排序
两两交换,每一轮比较使最大沉到最右边
*/

import java.util.Arrays;

public class BubbleOrder21 {
    public static void main(String[] args) {
//        趟数
        int tang = 0;
        //每趟比较的次数
        int count = 0;
        int[] arr = {1,2,3,4,5,7};
        boolean flag = true;
        //趟数 每趟产生一个值在最右端
        for (int i = 0; i < arr.length - 1; i++) {
            //比较的次数 由于每次都减少一个比较 所有减去i
            for (int j = 0; j < arr.length - i - 1; j++) {
                //如果前面的数大了,那么交换数据
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                    flag = false;
                }
                count++;
            }
            //if (flag) {
            //   break;
            //}
            System.out.println("次数:" + count);
            tang++;
        }
        System.out.println("趟数:" + tang);
        System.out.println(Arrays.toString(arr));
    }
}

​

4、冒泡排序优化

​
package com.huohua.day0408.code;

/*
冒泡排序
两两交换,每一轮比较使最大沉到最右边
*/

import java.util.Arrays;

public class BubbleOrder21 {
    public static void main(String[] args) {
//        趟数
        int tang = 0;
        //每趟比较的次数
        int count = 0;
        int[] arr = {1,2,3,4,5,7};
        boolean flag = true;
        //趟数 每趟产生一个值在最右端
        for (int i = 0; i < arr.length - 1; i++) {
            //比较的次数 由于每次都减少一个比较 所有减去i
            for (int j = 0; j < arr.length - i - 1; j++) {
                //如果前面的数大了,那么交换数据
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                    flag = false;
                }
                count++;
            }
            if (flag) {
                break;
            }
            System.out.println("次数:" + count);
            tang++;
        }
        System.out.println("趟数:" + tang);
        System.out.println(Arrays.toString(arr));
    }
}

​

4.5 二维数组

数组中的元素也是数组

4.5.1 二维数组的静态初始化

​
package com.huohua.day0409;

public class SecArray1 {
    public static void main(String[] args) {
        int[] arr1 = {1, 2, 3, 4, 5};
        int[] arr2 = new int[]{1, 2, 3, 4, 5};
//        二维数组初始化
        //静态初始化
        //方法一
        int[][] secArr1 = {{1, 2}, {3, 4, 5}, {6, 7, 8, 9, 0}};
        //方法二
        int[][] secArr2 = new int[][]{{1, 2}, {3, 4}, {5, 6}};
        int[][] secArr3;
        secArr3 = new int[][]{{1, 2}, {3, 4}, {5, 6}};
    }
}

​

4.5.2 获取二维数组长度

格式:数组名.length

int[][] secArr1 = {{1, 2}, {3, 4, 5}, {6, 7, 8, 9, 0}};
//二维数组的长度
System.out.println(secArr1.length);
//数组中数组的长度
for (int i = 0; i < secArr1.length; i++) {
    System.out.println(secArr1[i].length);
}

4.5.3 获取二维数组中的元素

格式:数组名[i][j]

i:代表的是一维数组在二维数组中的索引位置

j:代表的是元素在一维数组中的索引位置

int[][] secArr1 = {{1, 2}, {3, 4, 5}, {6, 7, 8, 9, 0}};
//二维数组中的数据 数组名【】【】
//三行 第三个
System.out.println("第三行第三个数据" + secArr1[2][2]);

4.5.4 二维数组的动态初始化

1.概述:数组中的套多个数组
2.定义格式
  a.动态初始化
    数据类型[ ][ ] 数组名 = new 数据类型[m][n]
    数据类型 数组名[ ][ ] = new 数据类型[m][n]
    数据类型[ ] 数组名[ ] = new 数据类型[m][n]
    
    m:代表的是二维数组的长度
    n:代表的是二维数组中每一个一维数组的长度

package com.huohua.day0409;

import java.util.Scanner;

public class SecArrayitra3 {
    public static void main(String[] args) {
        int[][] secArr = new int[5][3];
        Scanner scan = new Scanner(System.in);
        for (int i = 0; i <secArr.length ; i++) {
            for (int j = 0; j <secArr[i].length ; j++) {
//                System.out.println("请输入"+(i+1)+"行"+(j+1)+"列的值");
//                secArr[i][j]=scan.nextInt();
                secArr[i][j]=i*2;
            }
        }
        for (int i = 0; i <secArr.length ; i++) {
            //然后根据里层数组的长度分别再次遍历数组[][]
            for (int j = 0;j<secArr[i].length;j++){
                System.out.print(secArr[i][j]+" ");
            }
            System.out.println();
        }
    }
}
  • 47
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值