数组可以存放多个同一类型的数据。数组也是一种数据类型,是引用类型。 即:数(数据)组(一组) 就是一组数据
数组的使用 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¶
- 数组是多个相同类型数据的组合,实现对这些数据的统一管理
- 数组中的元素可以是任何数据类型,包括基本类型和引用类型,但是不能混用。
- 数组创建后:如果没有赋值,有默认值
int 0,short 0,byte 0,long 0,float 0.0,double 0.0,char \u0000,boolean false,String null
- 使用数组的步骤 1. 声明数组并开辟空间 2 给数组各个元素赋值 3 使用数组
- 数组的下标是从 0 开始的。
- 数组下标必须在指定范围内使用,否则报:下标越界异常,
- 比如
int[] arr = new int[5];则有效下标为 0-4
- 比如
- 数组属引用类型,数组型数据是对象(object)
数组练习 0161 #练习¶
- 创建一个 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 + " ");
}
}
-
请求出一个数组 int[] 的最大值(4,-1,9,10,23),并得到对应的下标。
-
请求出一个数组的和和平均值。(养鸡场)
数组赋值机制 0163¶
-
基本数据类型赋值,这个值就是具体的数据,而且相互不影响。
int n 1=2; int n 2=n 1; -
数组在默认情况下是引用传递,赋的值是地址。
int[] arr 1 = {1,2,3});int[] arr 2 = arrl; -
[[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)
- 用户可以通过如下方法来决定是否继续添加,添加成功,是否继续?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 的存储方式:
arr变量 (存储在栈中) 存储的是一个指向堆内存地址0x0011的引用。- 在堆内存地址
0x0011处,存储的是一个数组,这个数组的元素是两个引用:arr[0]指向地址0x0022arr[1]指向地址0x0033
- 在堆内存地址
0x0022处,存储的是arr[0]对应的数组,即arr[0][0]、arr[0][1]和arr[0][2]的值,它们都是 0。 - 在堆内存地址
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:动态初始化¶
- 先声明:
类型数组名[][] - 再定义(开辟空间)
数组名=new 类型[大小][大小] - 赋值(有默认值,比如 int 类型的就是 0)
- 使用演示
使用方式 3:动态初始化-列数不确定¶
看一个需求:动态创建下面二维数组,并输出。
列数不确定代表每个一维字数组中的元素个数不确定 -> 每一行的 y 值可以不一样 注意需要开辟一维数组的每个字数组的空间
Arrays. fill 可以用于填充数组
**使用方式 4:静态初始化¶
- 定义:
类型 数组名 = {{值 1,值 2...},{值 1,值 2,...},{值 1, 值 2,...}} - 使用即可 固定方式访问
int[][] arr = {{1,1,1}, {8,8,9}, {100});解读
- 定义了一个二维数组 arr
- arr 有三个元素(每个元素都是一维数组)
- 第一个一维数组有 3 个元素,第二个一维数组有 3 个元素,第三个一维数组有 1 个 元素
杨辉三角 0181 #练习¶
- 第一行有 1 个元素,第 n 行有 n 个元素
- 每一行的第一个元素和最后一个元素都是 1
- 从第三行开始,对于非第一个元素和最后一个元素的元素的值
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¶
-
一维数组的声明方式有:
int[] x或者int x[] -
.二维数组的声明方式有:
int[][] y或者int[] y[]或者int y[][]int[] y[]: 理解成不伦不类,实则一维数组里内容是二维数组int[]类型的y,开辟了[] -
二维数组实际上是由多个一维数组组成的,它的各个一维数组的长度可以相同,也可以不相同。
- 比如:
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 #练习¶
- 下面数组定义正确的有
-
写出结果 ![[数据类型#基本数据类型默认值]]
-
以下 Java 代码的输出结果为()
int num = 1;
while (num < 10) {
System.out.printIn(num);
if (num > 5) {
break;
}
num += 2;
}
// 1 3 5 7
- 已知有个升序的数组,要求插入一个元素,该数组顺序依然是升序,比如:
{ 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 + " ");
}
}
}
- 随机生成 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);
}
}
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
- 写出冒泡排序的代码 ![[0155 - 0189 第六章 数组、排序和查找#冒泡排序]]