Skip to content

1.数组概述

数组可以存放多个同一类型的数据。数组也是一种数据类型,是引用类型。
即:数(数据)组(一组)就是一组数据

java
//定义一个数组
double[] hens = {3,5,7,9,3.5,4.8};

//for循环得到数组所有元素的值
for(int i = 0;i < 6;i++){
    System.out.println(hens[i]);
}

img_59.png

2.数组的使用

使用方法1-动态初始化
数组类型 数组名[] = new 数据类型[大小]
int a[] = new int[5];//创建一个数组,名字为a,数组存放5个int
说明: 这是定义数组的一种方法,数组内存图如下
img_60.png

也可以先声明数组
语法:数据类型 数组名[]; 也可以 数据类型[] 数组名;
int a[]; 或者 int[] a;
然后创建数组
语法: 数组名 = new 数据类型[大小];
a = new int[10];

使用案例
循环输入五个成绩,保存到double数组,并输出

java
//演示 数据类型 数组名[]=new 数据类型[大小]
//循环输入 5 个成绩,保存到 double 数组,并输出
//步骤
//1. 创建一个 double 数组,大小 5
//(1) 第一种动态分配方式
//double scores[] = new double[5];
//(2) 第 2 种动态分配方式, 先声明数组,再 new 分配空间
double scores[]; //声明数组, 这时 scores 是 null
scores = new double[5]; // 分配内存空间,可以存放数据
//2. 循环输入
//scores.length //表示数组的大小/长度
Scanner myScanner = new Scanner(System.in);
for( int i = 0; i < scores.length; i++) {
    System.out.println("请输入第"+ (i+1) +"个元素的值");
    scores[i] = myScanner.nextDouble();
}
//输出,遍历数组
System.out.println("==数组的元素/值的情况如下:===");
for( int i = 0; i < scores.length; i++) {
    System.out.println("第"+ (i+1) +"个元素的值=" + scores[i]);
}

img_61.png

使用方法2-静态初始化
语法: 数据类型 数组名[] = {元素值,元素值...}
int a[] = {2,5,6,7,8,89,90,34,56};
这种方式使用动态初始化的方式就是:
int a[] = new int[9];
a[0] = 2; a[1] = 5; a[2] = 6; a[3] = 7; a[4] = 8; a[5] = 89; a[6] = 90; a[7] = 34; a[8] = 56;

3.数组的使用细节

  1. 数组是多个相同类型数据的组合,实现对这些数据的统一管理
  2. 数组中的元素可以是任何数据类型,包括基本类型和引用类型,但是不能混用
  3. 数组创建后,如果没有赋值,有默认值
    int 0, short 0, byte 0, long 0, float 0.0, double 0.0, char \u0000, boolean false, String null
  4. 使用数组的步骤 1. 声明数组并开辟空间 2. 给数组各个元素赋值 3. 使用数组
  5. 数组的下标是从0开始的
  6. 数组下标必须在指定范围内使用,否则报: 下标越界异常,比如 int[] arr = new int[5]; 则有效下标为 0-4
  7. 数组属引用类型,数组型数据是对象(object)

4.数组使用案例

  1. 创建一个char类型的26个元素的数组,分别放置'A'-'Z'。使用for循环访问所有元素并打印出来。
    提示: char类型数据运算'A'+2 -> 'C'
java
public class ArrayExercise01 {
    //编写一个 main 方法
    public static void main(String[] args) {
        /*
        创建一个 char 类型的 26 个元素的数组,分别 放置'A'-'Z'。
        使用 for 循环访问所有元素并打印出来。
        提示:char 类型数据运算 'A'+1 -> 'B' 
        思路分析
        1. 定义一个 数组 char[] chars = new char[26]
        2. 因为 'A' + 1 = 'B' 类推,所以老师使用 for 来赋值
        3. 使用 for 循环访问所有元素
        */
        char[] chars = new char[26];
        for( int i = 0; i < chars.length; i++) {//循环 26 次
            //chars 是 char[]
            //chars[i] 是 char
            chars[i] = (char)('A' + i); //'A' + i 是 int , 需要强制转换
        }
        //循环输出
        System.out.println("===chars 数组===");
        for( int i = 0; i < chars.length; i++) {//循环 26 次
            System.out.print(chars[i] + " ");
        }
    }
}

img_62.png

  1. 请求出一个数组int[]的最大值 {4,-1,9, 10,23},并得到对应的下标。
java
public class ArrayExercise02 {
    //编写一个 main 方法
    public static void main(String[] args) {
        //请求出一个数组 int[]的最大值 {4,-1,9, 10,23},并得到对应的下标
        //老韩思路分析
        //1. 定义一个 int 数组 int[] arr = {4,-1,9, 10,23};
        //2. 假定 max = arr[0] 是最大值 , maxIndex=0;
        //3. 从下标 1 开始遍历 arr, 如果 max < 当前元素,说明 max 不是真正的
        //最大值, 我们就 max=当前元素; maxIndex=当前元素下标
        //4. 当我们遍历这个数组 arr 后 , max 就是真正的最大值,maxIndex 最大值
        //对应的下标
        int[] arr = {4,-1,9,10,23};
        int max = arr[0];//假定第一个元素就是最大值
        int maxIndex = 0; //
        for(int i = 1; i < arr.length; i++) {//从下标 1 开始遍历 arr
            if(max < arr[i]) {//如果 max < 当前元素
                max = arr[i]; //把 max 设置成 当前元素
                maxIndex = i;
            }
         }
        //当我们遍历这个数组 arr 后 , max 就是真正的最大值,maxIndex 最大值下标
        System.out.println("max=" + max + " maxIndex=" + maxIndex);
    }
}

img_63.png

5.数组赋值机制

  1. 基本数据类型赋值,这个值就是具体的数据,而且相互不影响。赋值方式为值拷贝,n2的变化不会影响n1
    int n1 = 2; int n2 = n1; n2 = 80;
  2. 数组在默认情况下是引用传递,赋的值是地址。arr2的变化会影响arr1 看一个案例,并分析数组赋值的内存图。
java
int n1 = 10;
int n2 = n1;
n2 = 80;
System.out.println("n1=" + n1);//10
System.out.println("n2=" + n2);//80

int[] arr1 = {1,2,3};
for (int i = 0; i < arr1.length; i++) {
    System.out.println("arr1 =" + arr1[i]);//1 2 3
}
int[] arr2 = arr1;
arr2[0]=10;
for (int i = 0; i < arr2.length; i++) {
    System.out.println("arr2 =" + arr2[i]);//10 2 3
}
for (int i = 0; i < arr1.length; i++) {
    System.out.println("arr1 =" + arr1[i]);//10 2 3
}

img_64.png

流程分析
img_65.png

6.数组的拷贝

将int[] arr1 = {10,20,30}; 拷贝到arr2数组,要求数据空间是独立的

java
public class ArrayCopy {
    //编写一个 main 方法
    public static void main(String[] args) {
        //将 int[] arr1 = {10,20,30}; 拷贝到 arr2 数组, 
        //要求数据空间是独立的. 
        int[] arr1 = {10,20,30};
        //创建一个新的数组 arr2,开辟新的数据空间
        //大小 arr1.length;
        int[] arr2 = new int[arr1.length];
        //遍历 arr1 ,把每个元素拷贝到 arr2 对应的元素位置
        for(int i = 0; i < arr1.length; i++) {
            arr2[i] = arr1[i];
        }
        //老师修改 arr2, 不会对 arr1 有影响. 
        arr2[0] = 100;
        //输出 arr1
        System.out.println("====arr1 的元素====");
        for(int i = 0; i < arr1.length; i++) {
            System.out.println(arr1[i]);//10,20,30
        }
        //
        System.out.println("====arr2 的元素====");
        for(int i = 0; i < arr2.length; i++) {
            System.out.println(arr2[i]);//
        }
    }
}

7.数组的反转

要求: 把数组的元素内容反转。 arr {11,22,33,44,55,66} {66, 55,44,33,22,11}
方式1

java
public class ArrayReverse {
    //编写一个 main 方法
    public static void main(String[] args) {
        //定义数组
        int[] arr = {11, 22, 33, 44, 55, 66};
        //老韩思路
        //规律
        //1. 把 arr[0] 和 arr[5] 进行交换 {66,22,33,44,55,11}
        //2. 把 arr[1] 和 arr[4] 进行交换 {66,55,33,44,22,11}
        //3. 把 arr[2] 和 arr[3] 进行交换 {66,55,44,33,22,11}
        //4. 一共要交换 3 次 = arr.length / 2
        //5. 每次交换时,对应的下标 是 arr[i] 和 arr[arr.length - 1 -i]
        //代码
        //优化
        int temp = 0;
        int len = arr.length; //计算数组的长度
        for( int i = 0; i < len / 2; i++) {
            temp = arr[len - 1 - i];//保存
            arr[len - 1 - i] = arr[i];
            arr[i] = temp;
        }
        System.out.println("===翻转后数组===");
        for(int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + "\t");//66,55,44,33,22,11
        }
    }
}

方式2

java
public class ArrayReverse02 {
    //编写一个 main 方法
    public static void main(String[] args) {
        //定义数组
        int[] arr = {11, 22, 33, 44, 55, 66};
        //使用逆序赋值方式
        //老韩思路
        //1. 先创建一个新的数组 arr2 ,大小 arr.length
        //2. 逆序遍历 arr ,将 每个元素拷贝到 arr2 的元素中(顺序拷贝)
        //3. 建议增加一个循环变量 j -> 0 -> 5
        int[] arr2 = new int[arr.length];
        //逆序遍历 arr
        for(int i = arr.length - 1, j = 0; i >= 0; i--, j++) {
            arr2[j] = arr[i];
        }
        //4. 当 for 循环结束,arr2 就是一个逆序的数组 {66, 55, 44,33, 22, 11}
        //5. 让 arr 指向 arr2 数据空间, 此时 arr 原来的数据空间就没有变量引用
        //会被当做垃圾,销毁
        arr = arr2;
        System.out.println("====arr 的元素情况=====");
        //6. 输出 arr 看看
        for(int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + "\t");
        }
    }
}

8.数组的添加扩容

要求: 实现动态的给数组添加元素效果,实现对数组扩容。

  1. 原始数组使用静态分配 int[] arr = {1,2,3}
  2. 增加的元素4,直接放在数组的最后 arr = {1,2,3,4}
  3. 用户可以通过如下方法来决定是否继续添加,添加成功,是否继续?y/n
java
//获取输入对象
Scanner scanner = new Scanner(System.in);

//定义开始数组
int[] arr = {1,2,3,4};

//每次进入程序先给目标数组扩容
do {
    //扩容方式
    int[] arrNew = new int[arr.length + 1];
    for (int i = 0; i < arr.length; i++) {
        arrNew[i] = arr[i];
    }

    //将输入的元素放在扩容后新数组的最后一位
    arrNew[arrNew.length - 1] = scanner.nextInt();

    arr = arrNew;

    System.out.println("扩容后");

    for (int i : arrNew) {
        System.out.println(i + "\t");
    }

    System.out.println("是否继续添加");

    //获取用户输入的字符
    char c = scanner.next().charAt(0);

    //如果输入n则代表不添加退出循环
    if (c == 'n'){
        break;
    }
}while (true);


System.out.println("你退出了添加...");
}

9.数组的排序

内部排序: 指将需要处理的所有数据都加载到内部存储器中进行排序。包括(交换式排序法、选择式排序法和插入式排序法);
外部排序: 数据量过大,无法全部加载到内存中,需要借助外部存储进行排序。包括(合并排序法和直接合并排序法)。

冒泡排序
冒泡排序(Bubble Sorting)的基本思想是: 通过对待排序序列从后向前(从下标较大的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从前移向后部,就象水底下的气泡一样逐渐向上冒。

实验案例
下面我们举一个具体的案例来说明冒泡法。我们将五个无序: 24,69,80,57,13 使用冒泡排序法将其排成一个从小到大的有序数列。 img_66.png

先使用次循环重复写数组长度-1次得到最后结果

java
int[] arr = {24,69,80,57,13};
int temp = 0;
//第一次需要找到最大的数80,那么需要比较四次前后坐标进行比较
for (int j = 0; j < 4; j++) {
    if (arr[j] > arr[j+1]) {
        temp = arr[j];
        arr[j] = arr[j+1];
        arr[j+1] = temp;
    }
}
System.out.println("\n" + "第一轮");
for (int i : arr) {
    System.out.print(i + "\t");
}

//第一轮已经找出最大的80,那么接下来只需要依次比较 3 2 1 次
for (int j = 0; j < 3; j++) {
    if (arr[j] > arr[j+1]) {
        temp = arr[j];
        arr[j] = arr[j+1];
        arr[j+1] = temp;
    }
}
System.out.println("\n" + "第二轮");
for (int i : arr) {
    System.out.print(i + "\t");
}

//第一轮已经找出最大的80,那么接下来只需要依次比较 3 2 1 次
for (int j = 0; j < 2; j++) {
    if (arr[j] > arr[j+1]) {
        temp = arr[j];
        arr[j] = arr[j+1];
        arr[j+1] = temp;
    }
}
System.out.println("\n" + "第三轮");
for (int i : arr) {
    System.out.print(i + "\t");
}

//第一轮已经找出最大的80,那么接下来只需要依次比较 3 2 1 次
for (int j = 0; j < 1; j++) {
    if (arr[j] > arr[j+1]) {
        temp = arr[j];
        arr[j] = arr[j+1];
        arr[j+1] = temp;
    }
}
System.out.println("\n" + "第四轮");
for (int i : arr) {
    System.out.print(i + "\t");
}

将之前的数组长度-1次循环优化成一个外层for循环

java
int[] arr = {24,69,80,57,13,99,595,1661,4,456,36};
int temp = 0;
//第一次需要找到最大的数80,那么需要比较四次前后坐标进行比较
//因为每次找到一个最大数之后,在进行比较的次数就会照之前次数-1次
for (int i = 0; i < arr.length - 1; i++) {
    for (int j = 0; j < arr.length - 1 - i; j++) {
        if (arr[j] > arr[j + 1]) {
            temp = arr[j];
            arr[j] = arr[j + 1];
            arr[j + 1] = temp;
        }
    }
    System.out.println("\n" + "第"+ i +"轮");
    for (int iarr : arr) {
        System.out.print(iarr + "\t");
    }
}

img_67.png

10.数组的查找

案例演示
有一个数列: 白眉鹰王、金毛狮王、紫衫龙王、青翼蝠王猜数游戏
从键盘中任意输入一个名称,判断数列中是否 包含此名称[顺序查找] 要求: 如果找到了,就提示找到,并给出下标值。

String[] names = {"白眉鹰王", "金毛狮王", "紫衫龙王", "青翼蝠王"};
Scanner scanner = new Scanner(System.in);
String next = scanner.next();
int index = -1;
for (int i = 0; i < names.length; i++) {
    //用输入的名字数组中的名字进行比较
    if (names[i].equals(next)) {
        index = i;
        System.out.println("找到了" + (i +1));
    }
}
if (index == -1) {
    System.out.println("没有找到");
}

11.二维数组

11.1 案例分析

请用二维数组输出如下图形
0 0 0 0 0 0
0 0 1 0 0 0
0 2 0 3 0 0
0 0 0 0 0 0

java
int[][] arr = {{0, 0, 0, 0, 0, 0},
        {0, 0, 1, 0, 0, 0},
        {0, 2, 0, 3, 0, 0},
        {0, 0, 0, 0, 0, 0}};

for (int i = 0; i < arr.length; i++) {
    for (int j = 0;j < arr[i].length;j++) {
        System.out.print(arr[i][j] + " ");
    }
    System.out.println("");
}

img_68.png

二维数组分析

  1. 原来的一维数组的每个元素是一维数组,就构成了二维数组
  2. 二维数组的元素的个数用arr.length
  3. 由于二维数组的内部是arr.length个一维数组,所以要想访问第几个数组的第几个就是arr[i][j]个表示

11.2 二维数组的使用

使用方式1-动态初始化
语法: 类型[][] 数组名=new 类型[大小][大小]
比如: int a[][]=new int[2][3]
img_69.png

使用方式2-动态初始化
先声明:类型 数组名[][];
再定义(开辟空间) 数组名 = new 类型[大小][大小]
赋值(有默认值,比如int类型的就是 0)

使用方式3-动态初始化-列数不确定
img_70.png

java
//定义一个数组只指定有多少个一维数组不指定每个一维数组的大小
int[][] arr = new int[3][];

for (int i = 0; i < arr.length; i++) {
    //循环每个一位数组,给一维数组开辟空间
    arr[i] = new int[i + 1];
    for (int j = 0; j < arr[i].length; j++) {
        //循环每个一维数组为开辟的空间赋值
        arr[i][j] = i + 1;
    }
}

for (int i = 0; i < arr.length; i++) {
    for (int j = 0; j < arr[i].length; j++) {
        System.out.print(arr[i][j] + "\t");
    }
    System.out.println("");
}

使用方式4-静态初始化

定义: 类型 数组名[][] = {{值 1,值 2..},{值 1,值 2..},{值 1,值 2..}}使用即可[固定方式访问]     
比如:         
int[][] arr = {{1,1,1}, {8,8,9}, {100}};

解读

  1. 定义了一个二维数组 arr
  2. arr 有三个元素(每个元素都是一维数组)
  3. 第一个一维数组有3个元素,第二个一维数组有3个元素,第三个一维数组有1个元素

12.杨辉三角

img_71.png

java
//定义一个列数不确定二维数组
int[][] arr = new int[10][];

for (int i = 0; i < arr.length; i++) {
    //给每一个一维数组开辟响应的空间
    arr[i] = new int[i + 1];
    for (int j = 0; j < arr[i].length; j++) {
        //如果该位置是一维数组的第一个或者最后一个他就是1
        if (j == 0 || j == arr[i].length - 1){
            arr[i][j] = 1;
        }else {
            //如果不是第一个或者最后一个位置,就是上一个一维数组的相同列 + 前一列
            arr[i][j] = arr[i - 1][j] + arr[i - 1][j - 1];
        }
    }
}

for (int i = 0; i < arr.length; i++) {
    for (int j = 0; j < arr[i].length; j++) {
        System.out.print(arr[i][j] + " ");
    }
    System.out.println("");
}

13.二维数组的使用细节

1. 一维数组的声明方式有:    
   int[] x
   或者 int x[]
2. 二维数组的声明方式有:      
   int[][] y 或者 int[] y[] 或者 int y[][]
3. 二维数组实际上是由多个一维数组组成的,它的各个一维数组的长度可以相同,也可以不相同。           
   比如: map[][]是一个二维数组      
   int map [][] = {{1,2},{3,4,5}}     
   由map[0]是一个含有两个元素的一维数组,map[1]是一个含有三个元素的一维数组构成,我们也称为列数不等的二维数组

Released under the MIT License.