Skip to content

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

数组的使用 0157

使用方式 1 - 动态初始化

数组的定义

语法: 数据类型 数组名[] = new 数据类型[大小] int a[] = new int[5]://创建了一个数组,名字 a,存放 5 个 int

数组的引用(使用) 数组名[下标/索引] 比如:你要使用 a 数组的第 3 个数 a[2]

使用方式 2 - 动态初始化

先声明数组

语法:数据类型 数组名[];也可以 数据类型[] 数组名 int a[]; 或者 int[] a;

创建数组

语法:数组名 = new 数据类型[大小]; a=new int[10];

使用方式 3 - 静态初始化

初始化数组

语法:数据类型 数组名[] =(元素值,元素值...) - inta[]=(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;

double hens[] = (3,5,1,3.4,2,50);  
//等价  
double hens[] = new double[6];  
hens[0] = 3; hens[1] = 5; hens[2] = 1; hens[3] = 3.4; hens[4] = 2; hens[5] = 50;

数组注意事项 0160

  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)

数组练习 0161 #练习

  1. 创建一个 char 类型的 26 个元素的数组,分别放置'A'-'Z'。使用 for 循环访问所有元素并打印出来。
    • 提示:char 类型数据运算·A'+1->'B'

[[ArrayExercise01.java]]

public static void main(String[] args){  
    char[] chars = new char[26];  
    for(int i = 0; i < chars.length; i++){  
        chars[i] = (char)('a' + i);  
    };  
    for (char aChar : chars) {  
        System.out.print(aChar + " ");  
    }  
}

  1. 请求出一个数组 int[] 的最大值(4,-1,9,10,23),并得到对应的下标。

    public static void main(String[] args) {  
        int[] a = {4, -1, 9, 10, 23};  
        int max = a[0];  
        for (int x : a) {  
            if (max < x) {  
                max = x;  
            }  
        }  
        System.out.println(max);  
    }
    

  2. 请求出一个数组的和和平均值。(养鸡场)

    public static void main(String[] args) {  
        int[] hens = {5, 3, 2, 1, 4};  
        double average = 0;  
        for (int i = 0; i < hens.length; i++) {  
            average += (hens[i] - average) / (i + 1);  
        }  
        System.out.println(average);  
    }
    


数组赋值机制 0163

  1. 基本数据类型赋值,这个值就是具体的数据,而且相互不影响。 int n 1=2; int n 2=n 1;

  2. 数组在默认情况下是引用传递,赋的值是地址。 int[] arr 1 = {1,2,3}); int[] arr 2 = arrl;

  3. [[JVM]] 中数据的存储位置 ![[JVM#4. 堆(Heap) 堆]]


数组翻转 0165

方法一,互换对应元素位置

public static void main(String[] args) {  
    int[] a = {1, 2, 3, 4, 5, 6};  
    for (int i = 0; i < a.length / 2; i++) {  
        int temp = a[i];  
        a[i] = a[a.length - 1 - i];  
        a[a.length - 1 - i] = temp;  
    }  
    for (int x : a) {  
        System.out.print(x + " ");  
    }  
}

方法二,用新数组

public static void main(String[] args) {  
    int[] a = {1, 2, 3, 4, 5, 6};  
    int[] b = new int[a.length];  
    for (int x = 0; x < a.length; x++) {  
        b[x] = a[a.length-1-x];  
    }  
    a = b; // 用新数组的地址覆盖原数组
    for (int x : a) {  
        System.out.print(x + " ");  
    }  
}

数组扩容 0168

要求:实现动态的给数组添加元素效果,实现对数组扩容。 1. 原始数组使用静态分配 int[]arr=(1,2,3) 2. 增加的元素,直接放在数组的最后 arr={1,2,3,4)

  1. 用户可以通过如下方法来决定是否继续添加,添加成功,是否继续?y/n [[0155 - 0189 第六章 数组、排序和查找#实现用户控制添加]]

完成扩容

手动复制

public static void main(String[] args) {  
    int[] arr = {1, 2, 3};  
    int[] newArr = new int[arr.length + 1];  
    for (int i = 0; i < arr.length; i++){  
        newArr[i] = arr[i];  
    }  
    newArr[newArr.length - 1] = 4;  
    arr = newArr;  
    for (int x : arr){  
        System.out.print(x + " ");  
    }  
}

使用系统方法

  • 注意,clone() 方法是对原数组的[[拷贝#深拷贝]](基本数据类型),拷贝后数组元素和数组长度与原数组相同。
  • [[拷贝#System.arraycopy]]
public static void main(String[] args) {  
    int[] arr = {1, 2, 3};  
    int[] newArr = new int[arr.length + 1];  
    System.arraycopy(arr, 0, newArr, 0, arr.length);  
    // newArr = arr.clone();  
    newArr[newArr.length - 1] = 4;  
    arr = newArr;  
    for (int x : arr){  
        System.out.print(x + " ");  
    }  
}

实现用户控制添加

public static void main(String[] args) {  
    Scanner sc = new Scanner(System.in);  
    int[] arr = {1, 2, 3};  
    do{  
        int[] newArr = new int[arr.length + 1];  
        System.arraycopy(arr, 0, newArr, 0, arr.length);  

        System.out.println("请输入一个数字:");  
        newArr[newArr.length - 1] = sc.nextInt();  

        arr = newArr;  
        for (int x : arr){  
            System.out.print(x + " ");  
        }  
        System.out.println("是否继续添加? y/n");  
        char ch = sc.next().charAt(0);  
        if (ch != 'y')break;  
    }while (true);  

    for (int x : arr){  
        System.out.println("扩容后的数据");  
        System.out.print(x + " ");  
    }  
}

数组缩减 0169

  • 有一个数组(1,2.3,4,5),可以将该数组进行缩减,提示用户是否继续缩减,
  • 每次缩减最后那个元素。
  • 当只剩下最后一个元素,提示,不能再缩减。
public static void main(String[] args) {  
    Scanner sc = new Scanner(System.in);  
    int[] arr = {1, 2, 3, 4, 5};  
    while (true) {  
        System.out.println("数组元素为:");  
        for (int j : arr) {  
            System.out.print(j + " ");  
        }  
        if (arr.length == 1) {  
            System.out.println("数组中只有一个元素,不能再缩减");  
            break;  
        }  
        System.out.println("是否继续缩减?(y/n)");  
        if (sc.next().equals("y")) {  
            int[] newArr = new int[arr.length - 1];  
            System.arraycopy(arr, 0, newArr, 0, newArr.length);  
            arr = newArr;  
        }  
    }  
}

排序 0171

冒泡排序

注意遍历

public class Main {  
    public static void main(String[] args) {  
        int[] arr = {1, 5, 3, 7, 9, 2, 4, 6, 8, 0};  
        BubbleSort bubbleSort = new BubbleSort(arr);  
        for (int x : arr) {  
            System.out.print(x + " ");  
        }  
    }  
}  

class BubbleSort {  
    public BubbleSort(int[] arr) {  
        bubbleSort(arr);  
    }  

    public void bubbleSort(int[] arr) {  
        for (int times = 0; times < arr.length - 1; times++) {  
            for (int i = 0; i < arr.length - 1 - times; i++) {  
                if (arr[i] > arr[i + 1]) {  
                    System.out.println(arr[i] + "交换" + arr[i + 1]);  
                    int temp = arr[i + 1];  
                    arr[i + 1] = arr[i];  
                    arr[i] = temp;  
                }  
            }  
            for (int x : arr) {  
                System.out.print(x + " ");  
            }  
            System.out.println();  
        }  
    }  
}

查找 0174

顺序查找

import java.util.Scanner;  

public class Main {  
    public static void main(String[] args) {  
        String[] arr = {"Java", "C", "C++", "Python", "JavaScript", "PHP"};  
        Scanner sc = new Scanner(System.in);  
        System.out.println("请输入要查找的元素:");  
        String key = sc.next();  
        SeqSearch seqSearch = new SeqSearch(arr, key);  
    }  
}  
class SeqSearch{  
    SeqSearch(String[] arr, String key){  
        search(arr, key);  
    }  

    public void search(String[] arr, String key){  
        for(int x = 0; x < arr.length; x++){  
            if (arr[x].equals(key) ){  
                System.out.println("找到!");  
                System.out.println("下标未 " + x);  
                break;  
            }else if (x == arr.length - 1){  
                System.out.println("没有找到");  
            }  
        }  
    }  
}

二分查找


多维数组 0175

二维数组 TwoDimensionalArray

int [][] = {{1,2,3},{4,5,6}}

  • arr[i] 代表一位数组的第 i 个元素
  • arr[y][x] 代表第 y 个子元素(字数组)中的第 x 个元素(定位到单个元素)
    • int[][] arr = {{1,2,3}, {4,5,6}, {7,8,9}}
    • arr[y][x] 例如 arr[2][1] = 8 -> x = -3, y = -2
      • 可以理解成第三象限,其中 y , x 的值都是原数值 + 1 后取反。
    • 注意从 0 开始

二维数组的内存布局

栈里存放着二维数组的内存地址,这个内存地址指向堆的内存起始地址 堆内的起始地址 1 包含着一片地址空间,包含着多个堆内的元素的起始地址 2 起始地址 1 为整个二维数组的起始 【第一个参数】 起始地址 2 为单个子元素的内存起始地址 【第二个参数】

  • 栈 (Stack): 栈用于存储局部变量、方法调用等。图中显示 arr 变量存储在栈中,其值为 0x0011,这是一个内存地址。

  • 堆 (Heap): 堆用于存储对象实例。二维数组的实际数据存储在堆中。

  • 方法区 (Method Area): 方法区存储类的信息、常量、静态变量等。图中方法区位于底部。

二维数组 arr 的存储方式:

  1. arr 变量 (存储在栈中) 存储的是一个指向堆内存地址 0x0011 的引用。
  2. 在堆内存地址 0x0011 处,存储的是一个数组,这个数组的元素是两个引用:
    • arr[0] 指向地址 0x0022
    • arr[1] 指向地址 0x0033
  3. 在堆内存地址 0x0022 处,存储的是 arr[0] 对应的数组,即 arr[0][0]arr[0][1]arr[0][2] 的值,它们都是 0。
  4. 在堆内存地址 0x0033 处,存储的是 arr[1] 对应的数组,即 arr[1][0]arr[1][1]arr[1][2] 的值,分别为 0、8 和 0。

总结:

  • arr 在栈中存储的是一个引用(地址)。
  • 二维数组的每一行都是一个数组,这些数组存储在堆中。
  • arr[i] 存储的是第 i 行数组在堆中的地址。
  • arr[i][j] 存储的是第 i 行第 j 列的实际数值。

图示: ![[二维数组内存分布.png]]

graph LR
    subgraph JVM内存 [JVM的内存]
        direction LR
        subgraph 栈
            arr["arr ---> 0x0011"]
        end
        subgraph 堆
            direction TB
            arr0["arr[0]"]
            arr1["arr[1]"]
            arr0 --> 0x0022
            arr1 --> 0x0033
            subgraph 0x0022
                direction TB
                arr00["arr[0][0]"]
                arr01["arr[0][1]"]
                arr02["arr[0][2]"]
            end
            subgraph 0x0033
                direction TB
                arr10["arr[1][0]"]
                arr11["arr[1][1]"]
                arr12["arr[1][2]"]
            end
        end
        subgraph 方法区
        end
    end
    arr --> arr0
    arr --> arr1

二维数组的使用 0177

使用方式 1:动态初始化

  • 语法:类型[]]数组名=new 类型[大小][大小]
  • 比如: int a[][]=new int[2][3]

使用方式 2:动态初始化

  1. 先声明:类型数组名[][]
  2. 再定义(开辟空间)数组名=new 类型[大小][大小]
  3. 赋值(有默认值,比如 int 类型的就是 0)
  4. 使用演示
    int arr[][]; // 声明
    arr = new int [2][3];// 开辟空间
    int x = arr[1][1]; //使用
    

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

看一个需求:动态创建下面二维数组,并输出。

列数不确定代表每个一维字数组中的元素个数不确定 -> 每一行的 y 值可以不一样 注意需要开辟一维数组的每个字数组的空间

j i j = 0 j = 1 j = 2
i = 0 1
i = 1 2 2
i = 2 3 3 3
完成该案例
import java.util.Arrays;  

public class Main {  
    public static void main(String[] args) {  
        int [][] arr = new int[3][];  
        for(int i = 0;i< arr.length; i++){  
            arr[i] = new int[i+1]; // 开辟一维数组的空间  
        }  
        for(int i = 0;i< arr.length; i++){  
            Arrays.fill(arr[i], (i + 1));  
        }  
        //增强for输出二维数组  
        for(int[] row:arr){  
            for(int data:row){  
                System.out.print(data+" ");  
            }  
            System.out.println();  
        }  
    }  
}

Arrays. fill 可以用于填充数组

**使用方式 4:静态初始化

  1. 定义: 类型 数组名 = {{值 1,值 2...},{值 1,值 2,...},{值 1, 值 2,...}}
  2. 使用即可 固定方式访问
    • int[][] arr = {{1,1,1}, {8,8,9}, {100}); 解读
  3. 定义了一个二维数组 arr
  4. arr 有三个元素(每个元素都是一维数组)
  5. 第一个一维数组有 3 个元素,第二个一维数组有 3 个元素,第三个一维数组有 1 个 元素

杨辉三角 0181 #练习

  1. 第一行有 1 个元素,第 n 行有 n 个元素
  2. 每一行的第一个元素和最后一个元素都是 1
  3. 从第三行开始,对于非第一个元素和最后一个元素的元素的值
    • arr[i][j] = arr[i-1][j] + arr[i-1][j-1]
public class Main {  
    public static void main(String[] args) {  
        YanHui yh = new YanHui();  
        yh.print_YangHui(10);  
    }  
}  

class YanHui {  
    public void print_YangHui(int line) {  
        int[][] arr = new int[line][];  

        // 行数  
        for (int i = 0; i < line; i++) {  
            arr[i] = new int[i + 1];  

            for (int j = 0; j < i + 1; j++) {  
                if (j == 0 || j == i) {  
                    arr[i][j] = 1;  
                } else {  
                    arr[i][j] = arr[i - 1][j] + arr[i - 1][j - 1];  
                }  
            }  
        }  
        for (int i = 0; i < line; i++) {  
            for (int j = 0; j < arr[i].length; j++) {  
                System.out.print(arr[i][j] + " ");  
            }  
            System.out.println();  
        }  
    }  
}****

二维数组使用细节 0182

  1. 一维数组的声明方式有: int[] x 或者 int x[]

  2. .二维数组的声明方式有: int[][] y 或者 int[] y[] 或者 int y[][] int[] y[]: 理解成不伦不类,实则一维数组里内容是二维数组 int[] 类型的 y,开辟了 []

  3. 二维数组实际上是由多个一维数组组成的,它的各个一维数组的长度可以相同,也可以不相同。

    • 比如:map[][] 是一个二维数组
    • map [][]={{1,2},{3,4,5}}
    • 由于 map[0] 是一个含有两个元素的一维数组,
    • map[1] 是一个含有三个元素的一维数组构成,我们也称为列数不等的二维数组

二维数组练习 0183 #练习

声明:int[] x, y[]; 以下选项允许通过编译的是 0:

说明:x 是 int 一维数组, y 是 int 的二维数组

int[] x, y[];  

x[0] = y; // 错 二维——>一维
y[0] = X;  // 对
y[0][0] = x;  // 错 int[]-> int
x[0][0] = y;  // 错 x 一维
y[0][0] = x[0];  // 对
x = y; // 错 int[][] -> int[]

本章练习 0184 #练习

  1. 下面数组定义正确的有
    String strs[] = {'a','b','c'}; // wrong char -> String
    String[] strs = {"a", "b", "c"}; // right
    String[] strs = new String {"a" "b" "c"}; // wrong
    String strs[] = new String[] {"a", "b", "c"}: // right
    String[] strs = new String[3] {"a", "b", "c"}; // wrong
    
  2. 写出结果 ![[数据类型#基本数据类型默认值]]

    String foo = "blue";  
    boolean[] bar = new boolean[2];  
    if (bar[0]) {  
        foo = "green";  
    }
    System.out.println(foo);  
    
    // blue : Boolean 类型默认为 false
    

  3. 以下 Java 代码的输出结果为()

int num = 1;  
while (num < 10) {  
    System.out.printIn(num);  
    if (num > 5) {  
        break;  
    }  
    num += 2;
}  

// 1 3 5 7
  1. 已知有个升序的数组,要求插入一个元素,该数组顺序依然是升序,比如: { 10, 12, 45, 90 }, 添加 23 后, 数组为{ 10, 12, 23,45,90 }
public class Main {  
    public static void main(String[] args) {  
        int[] arr = {1, 12, 45, 90};  
        int[] newArr = new int[arr.length + 1];  

        int number = 2;  

        int i = 0;  
        if (arr[arr.length-1] < number){  
            for(int x: arr){  
                newArr[i] = x;  
                i++;  
            }  
            newArr[arr.length] = number;  
        } else if (arr[0] > number) {  
            newArr[0] = number;  
            i++;  
            for (int x : arr) {  
                newArr[i] = x;  
                i++;  
            }  
        }else{  
            for (int j = 0; j < arr.length; j++) {  
                if (arr[j] < number && arr[j + 1] < number) {  
                    newArr[i] = arr[j];  
                    i++;  
                } else if (arr[j] < number && arr[j + 1] > number) {  
                    newArr[i] = arr[j];  
                    newArr[i + 1] = number;  
                    i+=2;  
                }  else {  
                    newArr[i] = arr[j];  
                    i++;  
                }  
            }  
        }  

        arr = newArr;  

        for (  
                int x : arr) {  
            System.out.print(x + " ");  
        }  
    }  
}
先遍历找到放入的位置 Index
 number 加入
  1. 随机生成 10 个整数(1_100 的范围)保存到数组,并倒序打印以及求平均值、求最大 值和最大值的下标、并查找里面是否有 8

Math.random()是令系统随机选取大于等于 0.0 且小于 1.0 的伪随机 double 值*

public class Main {  
    public static void main(String[] args) {  
        int[] arr = new int[10];  
        for (int i = 0; i < arr.length; i++) {  
            arr[i] = (int) (Math.random() * 100) + 1;  
        }  

        System.out.println("逆序输出:");  
        for (int i = arr.length - 1; i >= 0; i--) {  
            System.out.print(arr[i] + " ");  
        }  

        System.out.println("最大值");  
        int max = arr[0];  
        int maxIndex = 0;  
        for (int i = 1; i < arr.length; i++){  
            if (max < arr[i]){  
                max = arr[i];  
                maxIndex = i;  
            }  
        }  
        System.out.print("最大值是:" + max);  
        System.out.print("最大值索引是:" + maxIndex);  

    }  
}
5. 试写出以下代码的打印结果
char[] arr1 = {'a', 'z', 'b', 'c'};  
char[] arr2 = arr1;  
arr1[2] = '韩';  
for (int i = 0; i < arr2.length;  
     i++) {  
    System.out.println(arr1[i] + "," + arr2[i]);  
}

// a a z z 韩 韩 c c

  1. 写出冒泡排序的代码 ![[0155 - 0189 第六章 数组、排序和查找#冒泡排序]]