一、知识点
1.数组的概述
- 数组,就可以理解为多个数据的组合。
- 是程序中的容器:数组、集合框架(第12章,List、Set、Map)。
- 数组存储的数据的特点:依次紧密排列的、有序的、可以重复的。
- 此时的数组、集合框架都是在内存中对多个数据的存储。
- 数组的其它特点:一旦初始化,其长度就是确定的、不可更改的。
基本语法的知识点:
1. 数组的理解(Array)
概念:是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。
简称:地多个数据的组合
Java中的容器:数组、集合框架(第12章)。在内存中对多个数据的存储。
2.几个相关的概念
> 数据名
> 数组的元素(既内部存储的多个元素)
> 数组的下标、角标、小角标、索引、index(即找到指定数组元素所使用的编号)
> 数组的长度(既数组容器中存储的元素的个数)
3.数组的特点:
> 数组中的元素在内存中是依次紧密排列的,有序的。
> 数组,属于引用数据类型的变量。数组的元素,既可以是基本数据类型,也可以是引用数据类型。
> 数组,一旦初始化完成,共长度就确定了,并且长度不可更改。
> 创建数组对象会扎起内存中开辟一整块‘连续的空间’。占据的空间的大小,取决于数组的长度和数组中元素的类型。
4. 复习:变量按章数据类型的分类
4.1 基本数据类型: byte \ short \ int \ long \ char \ boolean \ float \ double
4.2 引用数据类型: 类、数组、接口、枚举、注解、记录
5. 数组的分类
5.1 按照元素的类型:基本数类型元素的数组,引用数据类型元素的数组
5.2 按照元素的维数来分:一维数组,二维数组,...
6. 一维数组的使用(6个基本点)
> 数组的声明和初始化
> 调用数组的指定元素
> 数组的属性:length,表示数组的长度
> 数组的遍历
> 数组元素的默认初始化值
> 一维数组的内存解析(难)
7. 数组元素的默认初始化值的情况
注意:以数组的动态初始化方式为例说明。
> 整型数组元素的默认初始化值:0
> 浮点型数组元素的默认初始化值:0.0
> 字符型数组元素的默认初始化值:0 (或理解为'\u0000')
> boolean型数组元素的默认初始化值:false
> 引用数据类型数组元素的默认初始化值:null
8. 一维数组的内存解析
8.1 Java中的内存结构是如何划分的?(主要关心JVM的运行时内存环境)
> 将内存区域划分为5个部分:程序计数器、虚拟机栈、本地方法栈、堆、方法区
> 与目前数组相关的内存结构: 比如:int[] arr = new int[]{1,2,3};
> 虚拟机栈:用于存放方法中声明的变量。比如:arr
> 堆:用于存放数组的实体(即数组中的所有元素)。比如:1,2,3
8.2 举例:具体一维数组的代码的内存解析
基本语法的代码1:
package com.atguigu1.one;
/**
* ClassName: OneArraryTest
* Package: com.atguigu1.one
* Description: 一维数组的基本使用
*
* @Author 随心油条
* @Create 2024/1/25 9:52
* @Version 1.0
*/
public class OneArraryTest {
public static void main(String[] args) {
// 1. 数组的声明与初始化
// 复习:变量的定义格式:数据类型 变量名 = 变量值
int num1 = 10;
int num2; //声明
num2 = 20; //初始化
// 1.1 声明数组
double[] prices;
// 1.2 数组的初始化
// 静态初始化:数组变量的赋值与数组元素的赋值操作同时进行。
prices = new double[]{20.32,43.21,43.22};
// 这里不能使用
// princes = {20.32,43.21,43.22};
// String[] foods;
// foods = new String[]{"拌海蜇","龙须菜","炝冬笋","玉兰片"};
// 数组的声明和初始化
// 动态初始化:数组变量的赋值与数组元素的赋值操作分开进行。
String[] foods = new String[4];
// 其他正确的方式
int arr[] = new int[4];
int[] arr1 = new int[]{1,2,3,4};
// 错误的方式
// int[] arr2 = new int[4]{1,2,3,4};//既有动态,又有静态 报错的原因为:同时使用维表达式和初始化创建数组是非法的
// int[3] arr3 = new int[]; //声明数组元素个数只能从后面的[]中声明
// 2.数组元素的调用
// 通过角标的方式,获取数组的元素
// 角标的范围从0开始,到数组的长度-1结束
System.out.println(prices[0]);
System.out.println(prices[2]);
// System.out.println(prices[4]);//异常:ArrayIndexOutOfBoundsException
foods[0] = "拌海蜇";
foods[1] = "龙须菜";
foods[2] = "炝冬笋";
foods[3] = "玉兰片";
// foods[4] = "酱茄子";//异常:ArrayIndexOutOfBoundsException
// 3.数组的长度:用来描述数组容器中容量的大小
// 使用length属性表示
System.out.println(foods.length);//4
System.out.println(prices.length);//3
// 4.如何遍历数组
// System.out.println(foods[0]);
// System.out.println(foods[1]);
// System.out.println(foods[2]);
// System.out.println(foods[3]);
for (int i = 0; i < foods.length; i++){
System.out.println(foods[i]);
}
}
}
基本语法的代码2:
package com.atguigu1.one;
/**
* ClassName: OneArraryTest1
* Package: com.atguigu1.one
* Description: 一维数组的基本使用(承接OneArrayTest.java)
*
* @Author 随心油条
* @Create 2024/1/25 10:47
* @Version 1.0
*/
public class OneArraryTest1 {
public static void main(String[] args) {
//5. 数组元素的默认初始化值
// 整形数组元素的默认初始化值:0
int[] arr1 = new int[3];
System.out.println(arr1[0]);//输出为0
// 整形数组元素的默认初始化值:0
short[] arry2 = new short[2];
for (int i = 0; i < arry2.length; i++) {
System.out.println(arry2[i]); //输出0
}
// 浮点型数组元素的默认初始化值:0.0
double[] arry3 = new double[4];
System.out.println(arry3[1]); //输出0.0
// 字符型数组元素的默认初始化值:0 (或理解为'\u0000')
char[] arry4 = new char[2];
System.out.println(arry4[1]);
if (arry4[1] == 0){
System.out.println("aaaa"); //输出aaaa
}
if (arry4[1] == '0'){
System.out.println("bbbb");
}
if (arry4[1] == '\u0000'){
System.out.println("cccc"); //输出cccc
}
System.out.println((arry4[0] + 1)); //输出1
// boolean型数组元素的默认初始化值:
boolean[] arry5 = new boolean[2];
System.out.println(arry5[0]); //输出false
// 引用数据类型数组元素的默认初始化值:null 而不是 "null"
String[] arry6 = new String[5];
System.out.println(arry6[0]); // 输出null
if (arry6[1] == null){
System.out.println("1111"); //输出1111
}
if (arry6[1] == "null"){
System.out.println("2222");
}
//6.数组的内存解析
int[] a1 = new int[]{1,2,3};
// int a2 = a1; //会报错:不兼容的类型: int[]无法转换为int
int[] a2 = a1; //没有new就没有新开辟空间,就用的a1的地址
a2[1] = 10;
System.out.println(a1[1]); //输出10
System.out.println(a1); //输出数组a1的地址[I@776ec8df 其中[表示数组,@表示地址,776ec8df表示地址的数值,且为十六进制
System.out.println(a2); //输出数组a2的地址[I@776ec8df
}
}
案例1:
package com.atguigu1.one.exer1;
/**
* 案例:"破解"房东电话
*
* 升景坊单间短期出租4个月,550元/月(水电煤公摊,网费35元/月),空调、卫生间、厨房齐全。屋内均是IT行业人士,喜欢安静。
* 所以要求来租者最好是同行或者刚毕业的年轻人,爱干净、安静。
*
*/
/**
* ClassName: ArrayExer
* Package: com.atguigu1.one.exer1
* Description: 案例
*
* @Author 随心油条
* @Create 2024/1/25 14:07
* @Version 1.0
*/
public class ArrayExer {
public static void main(String[] args) {
int[] arr = new int[]{ 8, 6, 1, 0, 3};
int[] index = new int[]{ 2, 4, 3, 1, 0, 4, 1, 2, 1, 4, 2};
String tel = "";
for (int i = 0; i < index.length; i++) {
int value = index[i];
tel += arr[value];
}
System.out.println("联系方式: " + tel);//输出:18013820100
}
}
案例2:
需求:
案例:输出英文星期几
用一个数组,保持星期一到星期天的7个英语但粗,从键盘输入1-7,显示对应的单词
{"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"}
拓展:一年12个月的存储
用一个数组,保存12个月的英语单词,从键盘输入1-12,显示对应的单词。
{"January","February","March","April","May","June","July","August","September","October","November","December"}
代码:
package com.atguigu1.one.exer2;
import java.util.Scanner;
/**
* ClassName: ArrayExer
* Package: com.atguigu1.one.exer2
* Description: 案例:输出英文星期几
*
* 用一个数组,保存星期一到星期天的7个英语单词,从键盘输入1-7,显示对应的单词
* {"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"}
*
* @Author 随心油条
* @Create 2024/1/25 14:15
* @Version 1.0
*/
public class ArrayExer02 {
public static void main(String[] args) {
// 定义包含7个单词的数组
String[] weeks = new String[]{ "Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"};
// 从键盘获取指定的数值,使用Scanner
Scanner input = new Scanner(System.in);
System.out.print("请输入1-7的整数: ");
int chooes = input.nextInt();
// 没有定义数组的时候就这么做,现在定义数组了就换种方式.
// switch (chooes) {
// case 1:
// System.out.println("您的结果为: " + weeks[0]);
// break;
// case 2:
// System.out.println("您的结果为: " + weeks[1]);
// break;
// case 3:
// System.out.println("您的结果为: " + weeks[2]);
// break;
// case 4:
// System.out.println("您的结果为: " + weeks[3]);
// break;
// case 5:
// System.out.println("您的结果为: " + weeks[4]);
// break;
// case 6:
// System.out.println("您的结果为: " + weeks[5]);
// break;
// case 7:
// System.out.println("您的结果为: " + weeks[6]);
// break;
// }
// 针对获取的数据进行判断即可
if (chooes < 1 || chooes > 7){
System.out.println("您的输入有误!!");
}else {
System.out.println("您的结果为:" + weeks[chooes - 1]);
}
input.close();
}
}
案例3:
需求:
案例:学生考试等级划分
从键盘读入学生成绩,找出最高分,并输出学生成绩等级。
成绩>=最高分-10 等级为’A’
成绩>=最高分-20 等级为’B’
成绩>=最高分-30 等级为’C’
其余 等级为’D’
提示:先读入学生人数,根据人数创建int数组,存放学生成绩。
代码1:
package com.atguigu1.one.exer3;
import java.util.Scanner;
/**
* ClassName: ArrayExer03
* Package: com.atguigu1.one.exer3
* Description: 从键盘读入学生成绩,找出最高分,并输出学生成绩等级。
*
* * 成绩>=最高分-10 等级为’A’
* * 成绩>=最高分-20 等级为’B’
* * 成绩>=最高分-30 等级为’C’
* * 其余 等级为’D’
*
* @Author 随心油条
* @Create 2024/1/25 14:35
* @Version 1.0
*/
public class ArrayExer03 {
public static void main(String[] args) {
//1.从键盘数入学生的人数,根据人数,创建数组(动态初始化)
Scanner input = new Scanner(System.in);
System.out.print("请输入学生的人数: ");
int studentNum = input.nextInt();
int[] num = new int[studentNum];
//2.根据提示,依次输入学生成绩,并将成绩保存在数组元素中
System.out.println("请依次输入学生成绩: ");
int[] scores = new int[studentNum];
for (int i = 0; i < studentNum; i++) {
int score = input.nextInt();
scores[i] =score;
}
//3.获取学生成绩的最大值
int maxScore = scores[0];
for (int i = 1; i < scores.length; i++){
if (maxScore < scores[i]){
maxScore = scores[i];
}
}
System.out.println("学生成绩最大值为: " + maxScore);
//4.遍历数组元素,根据学生成绩与最高分的差值,得到每个学生的等级,并输出成绩和等级
for (int i = 0; i < scores.length; i++){
if (maxScore - scores[i] <= 10){
System.out.println("student[" +i +"]的成绩为: " + scores[i] + '\t' + "等级为A");
} else if (maxScore - scores[i] <= 20) {
System.out.println("student[" +i +"]的成绩为: " + scores[i] + '\t' + "等级为B");
}else if (maxScore - scores[i] <= 30) {
System.out.println("student[" +i +"]的成绩为: " + scores[i] + '\t' + "等级为C");
}else {
System.out.println("student[" +i +"]的成绩为: " + scores[i] + '\t' + "等级为D");
}
}
//关闭资源
input.close();
}
}
代码2:
package com.atguigu1.one.exer3;
import java.util.Scanner;
/**
* ClassName: ArrayExer03_1
* Package: com.atguigu1.one.exer3
* Description: 基于ArrayExer03的改进
*
* @Author 随心油条
* @Create 2024/1/25 15:26
* @Version 1.0
*/
public class ArrayExer03_1 {
public static void main(String[] args) {
//1.从键盘数入学生的人数,根据人数,创建数组(动态初始化)
Scanner input = new Scanner(System.in);
System.out.print("请输入学生的人数: ");
int studentNum = input.nextInt();
int[] num = new int[studentNum];
//2.根据提示,依次输入学生成绩,并将成绩保存在数组元素中
System.out.println("请依次输入学生成绩: ");
int[] scores = new int[studentNum];
int maxScore = scores[0];//scores[0]=0
for (int i = 0; i < studentNum; i++) {
int score = input.nextInt();
scores[i] =score;
//3.获取学生成绩的最大值
if (maxScore < scores[i]){
maxScore = scores[i];
}
}
System.out.println("学生成绩最大值为: " + maxScore);
//4.遍历数组元素,根据学生成绩与最高分的差值,得到每个学生的等级,并输出成绩和等级
char grade = 0;
for (int i = 0; i < scores.length; i++){
if (maxScore - scores[i] <= 10){
grade = 'A';
} else if (maxScore - scores[i] <= 20) {
grade = 'B';
}else if (maxScore - scores[i] <= 30) {
grade = 'C';
}else {
grade = 'D';
}
System.out.println("student[" + i +"]的成绩为: " + scores[i] + "\t" + "等级为" + grade);
}
//关闭资源
input.close();
}
}
2.一维数组的使用(重要)
基本语法的知识点:
1. 二维数组的理解
- 对于二维数组的理解,可以看成是一维数组array1又作为另一个一维数组array2的元素而存在。
- 其实,从数组底层的运行机制来看,其实没有多维数组。
- 概念:数组的外层元素;数组的内层元素
2. 二维数组的使用(6个基本点)
> 数组的声明和初始化
int[] arr = new int[10];
String[] arr1 = new String[]{"Tom", "Jerry"};
> 调用数组的指定元素:使用角标、索引、index
>index从0开始!
> 数组的属性:length,表示数组的长度
> 数组的遍历
> 数组元素的默认初始化值
> 二维数组的内存解析(难)
前提:在main()中声明变量:int[] arr = new int[]{1,2,3};
>虚拟机栈:main()作为一个栈帧,压入栈空间中。在main()栈帧中,存储着arr变量。arr记录着数组实体的首地址值。
>堆:数组实体存储在堆空间中。
3. 二维数组元素的默认初始化值
3.1 动态初始化方式1:(比如:int[][] arr = new int[3][4])
1)外层元素,默认存储地址值。
2)内层元素,默认与一维数组元素的不同类型的默认值规定相同。
> 整型数组元素的默认初始化值:0
> 浮点型数组元素的默认初始化值:0.0
> 字符型数组元素的默认初始化值:0 (或理解为'\u0000')
> boolean型数组元素的默认初始化值:false
> 引用数据类型数组元素的默认初始化值:null
3.2 动态初始化方式2:(比如:int[][] arr = new int[3][])
1)外层元素,默认存储null,因为内层不存在,所有外层存储内存的地址为默认值,而数组是引用型数据,默认值为null。
2)内层元素,不存在的。如果调用会报错(NullPointerException)
基本语法的代码1:
package com.atguigu2.two;
/**
* ClassName: TwoArrayTest
* Package: com.atguigu2.two
* Description:
*
* @Author 随心油条
* @Create 2024/1/25 16:13
* @Version 1.0
*/
public class TwoArrayTest {
public static void main(String[] args) {
// 1.数组的声明与初始化
//复习一维数组的声明与初始化
//方式1:静态初始化:数组变量的赋值和数组元素的赋值同时进行
int[] arr1 = new int[]{1,2,3};
int[] arr2 = {1,2,3};
//二维数组的声明与初始化
//方式1:静态初始化:数组变量的赋值和数组元素的赋值同时进行
int[][] arr4 = new int[][]{{1,2,3},{4,5},{6,7,8,9}};
int[][] arr6 = {{1,2,3},{4,5},{6,7,8,9}};
//方式2:动态初始化:数组变量的赋值和数组元素的赋值分开进行
int[] arr3 = new int[3];
//二维数组的声明与初始化
//方式2:动态初始化:数组变量的赋值和数组元素的赋值分开进行
String[][] arr5 = new String[3][4];
double[][] arr7 = new double[3][];
// 其他正确的写法:
int arr8[][] = new int[][]{{1,2,3},{4,5},{6,7,8,9}};
int[] arr9[] = new int[][]{{1,2,3},{4,5},{6,7,8,9}};
int arr10[][] = {{1,2,3},{4,5},{6,7,8,9}};
String arr11[][] = new String[3][4];
//错误的写法:
// int[][] arr12 = new int[3][3]{{1,2,3},{4,5,6},{7,8,9}};
// int[3][3] arr10 = new int[][]{{1,2,3},{4,5,6},{7,8,9}};
// 2.数组元素的调用
// 针对于arr4来说,外层元素{1,2,3},{4,5},{6,7,8,9} 内层元素:1,2,3,4,5,6,7,8,9
// 调用内层元素
System.out.println(arr4[0][2]);//输出3
System.out.println(arr4[2][3]);//输出9
//调用外层元素
System.out.println(arr4[0]);//输出[I@776ec8df 其中[表示数组,@表示数组,776ec8df表示地址的数值
//测试arr5,arr6
arr5[0][1] = "Tom";
System.out.println(arr5[0][1]); //输出Tom
System.out.println(arr5[0]); // 输出[Ljava.lang.String;@4eec7777
arr7[0] = new double[3];
arr7[0][0] = 1.0;
// 3.数组的长度
System.out.println(arr4.length);//输出3
System.out.println(arr4[0].length);//输出3
System.out.println(arr4[1].length);//输出2
System.out.println(arr4[2].length);//输出4
// 4.如何遍历二元数组的每个元素
for (int i = 0; i < arr4.length; i++) {
for (int j = 0; j < arr4[i].length; j++) {
System.out.print(arr4[i][j] + "\t");
}
System.out.println();
}
}
}
基本语法的代码1:
package com.atguigu2.two;
/**
* ClassName: TwoArrayTest1
* Package: com.atguigu2.two
* Description:
*
* @Author 随心油条
* @Create 2024/1/25 16:13
* @Version 1.0
*/
public class TwoArrayTest1 {
public static void main(String[] args) {
//5. 数值元素的默认初始化值
//以动态初始化方式1说明:
//整形数组元素的默认初始化值分内外层
int[][] arr1 = new int[3][2];
//外层元素默认值:
System.out.println(arr1[0]);//输出地址[I@776ec8df
System.out.println(arr1[1]);//输出地址[I@4eec7777
//内层元素默认值:
System.out.println(arr1[0][0]);//输出整形的默认值0
//布尔类型数组元素的默认初始化值分内外层
boolean[][] arr2 = new boolean[3][2];
//外层元素默认值:
System.out.println(arr2[0]);//输出地址[Z@3b07d329
//内层元素默认值:
System.out.println(arr2[0][0]);//输出布尔类型的默认值false
//字符串类型数组元素的默认初始化值分内外层
String[][] arr3 = new String[3][2];
//外层元素默认值:
System.out.println(arr3[0]);//输出地址[Ljava.lang.String;@41629346
//内层元素默认值:
System.out.println(arr3[0][0]);//输出数组的默认值null
// ********************************
//以动态初始化方式2说明:
//整形数组元素的默认初始化值分内外层
int[][] arr4 = new int[3][];
//外层元素默认值:
System.out.println(arr4[0]);//输出数组的默认值null
//内层元素默认值:
// System.out.println(arr4[0][0]);//没有分配内存空间,所以会报错:NullPointerException
//字符串类型数组元素的默认初始化值分内外层
String[][] arr5 = new String[3][];
//外层元素默认值:
System.out.println(arr5[0]);//输出数组的默认值null
//内层元素默认值:
// System.out.println(arr5[0][0]);//没有分配内存空间,所以会报错:NullPointerException
}
}
案例1:
案例1:获取arr数组中所有元素的和。
提示:使用for的嵌套循环即可。
利用二维数组遍历求和,二维数组如图所示。
package com.atguigu2.two.exer1;
/**
* ClassName: ArrayExer01
* Package: com.atguigu2.two.exer1
* Description: 案例1:获取arr数组中所有元素的和
*
*提示:使用for的嵌套循环即可。
*
* @Author 随心油条
* @Create 2024/1/25 18:51
* @Version 1.0
*/
public class ArrayExer01 {
public static void main(String[] args) {
//初始化数组:使用静态初始化
int[][] arr1 = new int[][]{{3,5,8},{12,9},{7,0,6,4}};
int sum = 0;
for (int i = 0; i < arr1.length; i++) {
for (int j = 0; j < arr1[i].length; j++) {
sum += arr1[i][j];
}
}
System.out.println("总和为: " + sum);
}
}
案例2:
案例:声明:int[] x,y[]; 在给x,y变量赋值以后,以下选项允许通过编译的是:
声明:int[] x,y[]; 在给x,y变量赋值以后,以下选项允许通过编译的是: x:一维int[] y:二维int[][]
a) x[0] = y;
b) y[0] = x;
c) y[0][0] = x;
d) x[0][0] = y;
e) y[0][0] = x[0];
f) x = y;
提示:
一维数组:int[] x 或者int x[]
二维数组:int[][] y 或者 int[] y[] 或者 int y[][]
package com.atguigu2.two.exer2;
/**
* ClassName: ArrayExer02
* Package: com.atguigu2.two.exer2
* Description: 声明:int[] x,y[]; 在给x,y变量赋值以后,以下选项允许通过编译的是:
*
* 声明:int[] x,y[]; 在给x,y变量赋值以后,以下选项允许通过编译的是: x:一维int[] y:二维int[][]
*
* a) x[0] = y;
* b) y[0] = x;
* c) y[0][0] = x;
* d) x[0][0] = y;
* e) y[0][0] = x[0];
* f) x = y;
*
* 提示:
* 一维数组:int[] x 或者int x[]
* 二维数组:int[][] y 或者 int[] y[] 或者 int y[][]
*
* @Author 随心油条
* @Create 2024/1/25 18:57
* @Version 1.0
*/
public class ArrayExer02 {
public static void main(String[] args) {
// = :赋值符号.
int i = 10;
int j = i;
byte b = (byte)i; //强制类型转换
long l = i; //自动类型提升
//举例:数组
int[] arr2 = new int[10];
byte[] arr3 = new byte[20];
// arr2 = arr3;编译不通过,原因:int[]和byte[]是两种不同类型的引用变量
System.out.println(arr2);//输出[I@776ec8df
System.out.println(arr3);//输出[B@4eec7777
//声明
int[] x = new int[1];
int[][] y = new int[1][1];
//a) x[0] = y;
// x[0] = y;//报错:不兼容的类型: int[][]--->y 无法转换为 int--->x[0]
//b) y[0] = x;
y[0] = x; //可以通过编译,因为都是int[]类型
//c) y[0][0] = x;
// y[0][0] = x;//报错:不兼容的类型: int[]--->x 无法转换为 int--->y[0][0]
//d) x[0][0] = y;
// x[0][0] = y;//报错:需要数组--->y, 但找到int--->x[0][0]
//e) y[0][0] = x[0];
y[0][0] = x[0];//可以通过编译,因为都是int类型
//f) x = y;
// x = y;报错:不兼容的类型: int[][]--->y 无法转换为 int[]--->x
}
}
案例3:
需求:
案例:二维数组存储数据,并遍历
String[][] employees = {
{"10", "1", "段 誉", "22", "3000"},
{"13", "2", "令狐冲", "32", "18000", "15000", "2000"},
{"11", "3", "任我行", "23", "7000"},
{"11", "4", "张三丰", "24", "7300"},
{"12", "5", "周芷若", "28", "10000", "5000"},
{"11", "6", "赵 敏", "22", "6800"},
{"12", "7", "张无忌", "29", "10800","5200"},
{"13", "8", "韦小宝", "30", "19800", "15000", "2500"},
{"12", "9", "杨 过", "26", "9800", "5500"},
{"11", "10", "小龙女", "21", "6600"},
{"11", "11", "郭 靖", "25", "7100"},
{"12", "12", "黄 蓉", "27", "9600", "4800"}
};
其中"10"代表普通职员,"11"代表程序员,"12"代表设计师,"13"代表架构师。输出显示效果如图。
代码:
package com.atguigu2.two.exer3;
/**
* ClassName: ArrayExer03
* Package: com.atguigu2.two.exer3
* Description: 案例:二维数组存储数据,并遍历
*
* String[][] employees = {
* {"10", "1", "段 誉", "22", "3000"},
* {"13", "2", "令狐冲", "32", "18000", "15000", "2000"},
* {"11", "3", "任我行", "23", "7000"},
* {"11", "4", "张三丰", "24", "7300"},
* {"12", "5", "周芷若", "28", "10000", "5000"},
* {"11", "6", "赵 敏", "22", "6800"},
* {"12", "7", "张无忌", "29", "10800","5200"},
* {"13", "8", "韦小宝", "30", "19800", "15000", "2500"},
* {"12", "9", "杨 过", "26", "9800", "5500"},
* {"11", "10", "小龙女", "21", "6600"},
* {"11", "11", "郭 靖", "25", "7100"},
* {"12", "12", "黄 蓉", "27", "9600", "4800"}
* };
*
* 其中"10"代表普通职员,"11"代表程序员,"12"代表设计师,"13"代表架构师。显示效果如图。
*
* @Author 随心油条
* @Create 2024/1/25 19:07
* @Version 1.0
*/
public class ArrayExer03 {
public static void main(String[] args) {
String[][] employees = {
{"10", "1", "段 誉", "22", "3000"},
{"13", "2", "令狐冲", "32", "18000", "15000", "2000"},
{"11", "3", "任我行", "23", "7000"},
{"11", "4", "张三丰", "24", "7300"},
{"12", "5", "周芷若", "28", "10000", "5000"},
{"11", "6", "赵 敏", "22", "6800"},
{"12", "7", "张无忌", "29", "10800","5200"},
{"13", "8", "韦小宝", "30", "19800", "15000", "2500"},
{"12", "9", "杨 过", "26", "9800", "5500"},
{"11", "10", "小龙女", "21", "6600"},
{"11", "11", "郭 靖", "25", "7100"},
{"12", "12", "黄 蓉", "27", "9600", "4800"}
};
System.out.println("员工类型" + "\t" + "编号" + "\t" + "姓名" + "\t\t" + "年龄" + "\t" + "薪资" + "\t" + "\t奖金" + "\t" + "\t股票");
for (int i = 0; i < employees.length; i++) {
switch (employees[i][0]) {
case "10":
employees[i][0] = "普通职员";
break;
case "11":
employees[i][0] = "程序员";
break;
case "12":
employees[i][0] = "设计师";
break;
case "13":
employees[i][0] = "架构师";
break;
}
for (int j = 0; j < employees[i].length; j++) {
System.out.print(employees[i][j] + "\t");
}
System.out.println();
} }
}
3.二维数组的使用(难点)
基本语法的知识点:
【数组的常见算法1】
1. 数值型数组特征值统计
这里的特征值涉及到:平均值、最大值、最小值、总和等
2. 数组元素的赋值(实际开发中,遇到的场景比较多)
3. 数组的复制
4. 数组的反转
案例1:
需求:
案例:定义一个int型的一维数组,包含10个元素,分别赋一些随机整数,然后求出所有元素的最大值,最小值,总和,平均值,
并输出出来。
要求:所有随机数都是两位数:[10,99]
提示:求[a,b]范围内的随机数: (int)(Math.random() * (b - a + 1)) + a;
package com.atguigu3.common_algorithm.exer1;
/**
* ClassName: ArrayExer01
* Package: com.atguigu3.common_algorithm.exer1
* Description: 定义一个int型的一维数组,包含10个元素,分别赋一些随机整数,然后求出所有元素的最大值,最小值,总和,平均值,并输出出来。
*
* 要求:所有随机数都是两位数:[10,99]
* 提示:求[a,b]范围内的随机数: (int)(Math.random() * (b - a + 1)) + a;
*
* @Author 随心油条
* @Create 2024/1/25 20:22
* @Version 1.0
*/
public class ArrayExer01 {
public static void main(String[] args) {
//1.动态初始化方式创建数组
int[] arr = new int[10];
//2.通过循环给数组元素赋值
for (int i = 0; i < arr.length; i++){
arr[i] = (int) (Math.random() * 90) + 1;
}
//将所有的数遍历出来
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
//3.1求最大值
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
if(max < arr[i]){
max = arr[i];
}
}
System.out.println("\n最大值为: " + max);//最大值为: 70
//3.2求最小值
int min = arr[0];
for (int i = 0; i < arr.length; i++) {
if(min > arr[i]){
min = arr[i];
}
}
System.out.println("最小值为: " + min);//最小值为: 6
//3.3求总和
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
System.out.println("总和为: " + sum);//总和为: 317
//3.4求平均
int avgValue = 0;
avgValue = sum/(arr.length);
System.out.println("平均值为: " + avgValue);//平均值为: 31
}
}
案例2:
需求:
案例:评委打分
分析以下需求,并用代码实现:
(1)在编程竞赛中,有10位评委为参赛的选手打分,分数分别为:5,4,6,8,9,0,1,2,7,3
(2)求选手的最后得分(去掉一个最高分和一个最低分后其余8位评委打分的平均值)
package com.atguigu3.common_algorithm.exer2;
/**
* ClassName: ArrayExer02
* Package: com.atguigu3.common_algorithm.exer2
* Description: 评委打分
*
* 分析以下需求,并用代码实现:
*
* (1)在编程竞赛中,有10位评委为参赛的选手打分,分数分别为:5,4,6,8,9,0,1,2,7,3
*
* (2)求选手的最后得分(去掉一个最高分和一个最低分后其余8位评委打分的平均值)
*
* @Author 随心油条
* @Create 2024/1/25 20:37
* @Version 1.0
*/
public class ArrayExer02 {
public static void main(String[] args) {
int[] scores = new int[]{5,4,6,8,9,0,1,2,7,3};
//声明三个特征值
int sum = 0;
int max = scores[0];
int min = scores[0];
//求总和,最大值,最小值
for (int i = 0; i < scores.length; i++) {
sum += scores[i];
if (max < scores[i]){
max = scores[i];
}
if (min > scores[i]){
min = scores[i];
}
}
//求平均
int avrgScore = (sum-max-min)/(scores.length-2);
System.out.println("评委们打的平均分为: " + avrgScore);
}
}
案例3:
需求:
案例:使用二维数组打印一个 10 行杨辉三角。
提示:
1. 第一行有 1 个元素, 第 n 行有 n 个元素
2. 每一行的第一个元素和最后一个元素都是 1
3. 从第三行开始, 对于非第一个元素和最后一个元素的元素。即:
yanghui[i][j] = yanghui[i-1][j-1] + yanghui[i-1][j];
4.输出效果如图所示。
代码:
package com.atguigu3.common_algorithm.exer3;
/**
* ClassName: YangHuiTest
* Package: com.atguigu3.common_algorithm.exer3
* Description: 使用二维数组打印一个 10 行杨辉三角。
*
* 提示:
* 1. 第一行有 1 个元素, 第 n 行有 n 个元素
* 2. 每一行的第一个元素和最后一个元素都是 1
* 3. 从第三行开始, 对于非第一个元素和最后一个元素的元素。即:
* yanghui[i][j] = yanghui[i-1][j-1] + yanghui[i-1][j];
*
* @Author 随心油条
* @Create 2024/1/25 21:05
* @Version 1.0
*/
public class YangHuiTest {
public static void main(String[] args) {
//1. 创建二维数组
int[][] YangHui= new int[10][];//注意定义里面的数值和索引的偏移量是不一样的
//2.使用循环结构,初始化外层数组元素
for (int i = 0; i < YangHui.length; i++) {
YangHui[i] = new int[i + 1];//因为这里i只能到9,而新定义new int[i + 1]这里的(i + 1)要为10
//3. 给数组的元素赋值
//3.1 给数组每行的首末元素赋值为1
YangHui[i][i] = YangHui[i][0] = 1;
// if (i >= 2){
for (int j = 1; j < YangHui[i].length - 1; j++) { //j从每行的第2个元素开始(所以最开始初始化索引为1),到倒数第2个元素结束
YangHui[i][j] = YangHui[i - 1][j - 1] + YangHui[i - 1][j];
// }
}
}
for (int i = 0; i < YangHui.length; i++) {
for (int j = 0; j < YangHui[i].length; j++) {
System.out.print(YangHui[i][j] + "\t");
}
System.out.println();
}
}
}
案例4:
需求:
案例:复制、赋值
使用简单数组
(1)创建一个名为ArrayTest的类,在main()方法中声明array1和array2两个变量,他们是int[]类型的数组。
(2)使用大括号{},把array1初始化为8个素数:2,3,5,7,11,13,17,19。
(3)显示array1的内容。
(4)赋值array2变量等于array1,修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)。
(5)打印出array1。
思考:array1和array2是什么关系?
【answer】array1和array2是两个变量,共同指向了堆空间中的同一个数组结构。即二者的地址值相同。
拓展:修改题目,实现array2对array1数组的复制
代码1:
package com.atguigu3.common_algorithm.exer4;
/**
* ClassName: ArrayExer04
* Package: com.atguigu3.common_algorithm.exer4
* Description: 案例:数组的赋值
*
* 使用简单数组
* (1)创建一个名为ArrayTest的类,在main()方法中声明array1和array2两个变量,他们是int[]类型的数组。
* (2)使用大括号{},把array1初始化为8个素数:2,3,5,7,11,13,17,19。
* (3)显示array1的内容。
* (4)赋值array2变量等于array1,修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)。
* (5)打印出array1。
*
* 思考:array1和array2是什么关系?
* 【answer】array1和array2是两个变量,共同指向了堆空间中的同一个数组结构。即二者的地址值相同。
*
* 拓展:修改题目,实现array2对array1数组的复制
*
* @Author 随心油条
* @Create 2024/1/25 21:42
* @Version 1.0
*/
public class ArrayExer04 {
public static void main(String[] args) {
//使用简单数组
//(1)创建一个名为ArrayExer04的类,在main()方法中声明array1和array2两个变量,他们是int[]类型的数组。
int[] array1,array2;
//(2)使用大括号{},把array1初始化为8个素数:2,3,5,7,11,13,17,19。
array1 = new int[]{2,3,5,7,11,13,17,19};
//(3)显示array1的内容。
for (int i = 0; i < array1.length; i++) {
System.out.print(array1[i] + "\t");//输出2 3 5 7 11 13 17 19
}
System.out.println();//换行
//(4)赋值array2变量等于array1,修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)。
array2 = array1;
System.out.println(array1);//输出[I@58372a00
System.out.println(array2);//输出[I@58372a00
for (int i = 0; i < array1.length; i++) {
if(i % 2 == 0){
array1[i] = i;
}
}
//(5)打印出array1。
System.out.println();//换行
for (int i = 0; i < array1.length; i++) {
System.out.print(array1[i] + "\t");//输出0 3 2 7 4 13 6 19
}
}
}
代码2:
package com.atguigu3.common_algorithm.exer4;
/**
* ClassName: ArrayExer04_1
* Package: com.atguigu3.common_algorithm.exer4
* Description: 数组的复制
*
* @Author 随心油条
* @Create 2024/1/25 21:42
* @Version 1.0
*/
public class ArrayExer04_1 {
public static void main(String[] args) {
//使用简单数组
//(1)创建一个名为ArrayExer04的类,在main()方法中声明array1和array2两个变量,他们是int[]类型的数组。
int[] array1;
int[] array2;
//(2)使用大括号{},把array1初始化为8个素数:2,3,5,7,11,13,17,19。
array1 = new int[]{2,3,5,7,11,13,17,19};
//(3)显示array1的内容。
for (int i = 0; i < array1.length; i++) {
System.out.print(array1[i] + "\t");//输出2 3 5 7 11 13 17 19
}
System.out.println();//换行
//(4)复制array1数组给array2,修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)。
array2 = new int[array1.length];//没有这个语句会报这个错:可能尚未初始化变量array2,所以我们用动态初始化,通过array1的长度来初始化array2
for (int i = 0; i < array1.length; i++) {
array2[i] = array1[i];
}
System.out.println(array1);//输出[I@58372a00
System.out.println(array2);//输出[I@4dd8dc3
for (int i = 0; i < array1.length; i++) {
if(i % 2 == 0){
array1[i] = i;
}
}
//(5)打印出array1。
System.out.println();//换行
for (int i = 0; i < array1.length; i++) {
System.out.print(array1[i] + "\t");//输出2 3 5 7 11 13 17 19
}
}
}
内存解析1:
内存解析2:
案例5:
需求:
案例:
定义数组:int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67};
如何实现数组元素的反转存储?你有几种方法。
反转数组图示:
对称数组图示:
代码:
package com.atguigu3.common_algorithm.exer5;
/**
* ClassName: ArrayExer05
* Package: com.atguigu3.common_algorithm.exer5
* Description: 案例:元素反转,对称数组
*
* 定义数组:int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67};
* 如何实现数组元素的反转存储?你有几种方法。
*
* @Author 随心油条
* @Create 2024/1/25 21:55
* @Version 1.0
*/
public class ArrayExer05 {
public static void main(String[] args) {
//1. 定义数组:
int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67};
int temp;
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t"); //数组在转换之前输出一次,输出结果34 54 3 2 65 7 34 5 76 34 67
}
//方式1:(推荐)
// for (int i = 0; i < arr.length/2; i++) {
// 交互arr[i] 与 arr[arr.length - 1 - i]位置的元素
// temp = arr[i];
// arr[i] = arr[arr.length - 1 - i];
// arr[arr.length - 1 -i] = temp;
// }
//方式2:(推荐)
for (int i = 0, j = arr.length - 1 - i; i < j; i++, j--) {
//交互arr[i] 与 arr[j]位置的元素
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
// //方式3:(不建议,一,开辟一个新空间,二,遍历的次数太多)
// int[] newArray = new int[arr.length];
// for (int i = arr.length - 1; i >= 0; i--) {
// newArray[arr.length - 1 - i] = arr[i];
// }
// arr = newArray;
System.out.println();
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t"); //数组在转换之前输出一次,输出结果67 34 76 5 34 7 65 2 3 54 34
}
//对称数组的解决办法:
boolean isFlag = true;
int[] arr1 = new int[]{1,2,3,4,5,4,3,2,1};
for (int i = 0,j = arr1.length - 1; i < j; i++, j--) {
if (arr1[i] != arr1[j]){
isFlag = false;
}
}
System.out.println();
if(isFlag){
System.out.println("是对称数组");
}
}
}
4.数组的常用算法(重要)
基本语法的知识点:
【数组的常见算法2】
1. 数组的扩容与缩容
2. 数组元素的查找
顺序查找:
> 优点:算法简单;
> 缺点:执行效率低。执行的时间复杂度O(N)
二分法查找:
> 优点:执行效率高。执行的时间复杂度O(logN)
> 缺点:算法相较于顺序查找难一点;前提:数组必须有序
3. 数组的排序
排序算法的衡量标准:① 时间复杂度(最重要) ② 空间复杂度 ③ 稳定性
Ο(1)<Ο(log2n)<Ο(n)<Ο(nlog2n)<Ο(n<sup>2</sup>)<Ο(n<sup>3</sup>)<…<Ο(2<sup>n</sup>)<Ο(n!)<O(n<sup>n</sup>)
排序的分类:内部排序(内存中排序);外部排序(外部存储设备+内存)
内部排序的具体算法:10种。具体的见课件
我们需要关注的几个排序算法:
> 冒泡排序:最简单,需要大家会手写。时间复杂度:O(n^2)
> 快速排序:最快的,开发中默认选择的排序方式;掌握快速排序的实现思路;时间复杂度:O(nlogn)
案例1:
需求:
案例1:数组的扩容:
现有数组 int[] arr = new int[]{1,2,3,4,5};
现将数组长度扩容1倍,并将10,20,30三个数据添加到arr数组中,如何操作?
代码:
package com.stguigu4.search_sort.exer1;
/**
* ClassName: ArrayExer01_1
* Package: com.stguigu4.search_sort.exer1
* Description: 数组的扩容:
*
* 现有数组 int[] arr = new int[]{1,2,3,4,5};
* 现将数组长度扩容1倍,并将10,20,30三个数据添加到arr数组中,如何操作?
*
* @Author 随心油条
* @Create 2024/1/26 9:51
* @Version 1.0
*/
public class ArrayExer01_1 {
public static void main(String[] args) {
//1、初始化,声明int[] arr = new int[]{1,2,3,4,5};
int[] arr = new int[]{1,2,3,4,5};
System.out.println("原来数组arr的元素为:" + "\t");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
//2、现将数组长度扩容1倍,两种方法
// int[] arr1 = new int[arr.length * 2];// 使用乘法
int[] arr1 = new int[arr.length << 1];// 使用左移
//3、将原有数组中的元素复制到新的数组中并将10,20,30三个数据添加到arr数组中
for (int i = 0; i < arr.length; i++) {
arr1[i] = arr[i];
}
//4、将10,20,30三个数据添加到新数组中
arr1[arr.length] = 10;
arr1[arr.length + 1] = 20;
arr1[arr.length + 2] = 30;
//将新的数组的地址赋值给原有的数组变量
arr = arr1;
//换行
System.out.println();
//遍历arr
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
}
}
案例2:
需求:
案例:数组的缩容:
现有数组 int[] arr={1,2,3,4,5,6,7}。现需删除数组中索引为4的元素。
代码:
package com.stguigu4.search_sort.exer1;
/**
* ClassName: ArrayExer01_2
* Package: com.stguigu4.search_sort.exer1
* Description: 数组的缩容:
*
* 现有数组 int[] arr={1,2,3,4,5,6,7}。现需删除数组中索引为4的元素。
*
* @Author 随心油条
* @Create 2024/1/26 10:06
* @Version 1.0
*/
public class ArrayExer01_2 {
public static void main(String[] args) {
//数组的声明和初始化
int[] arr={1,2,3,4,5,6,7};
//方法1:推荐
//采用将索引为5的替换索引为4的元素,而不新创建数组
for (int i = 4; i < arr.length - 1; i++) {
arr[i] = arr[i +1];
}
for (int i = 0; i < arr.length; i++) {
//修改最后元素,设置为默认值
arr[arr.length - 1] = 0;
System.out.print(arr[i] + "\t");
}
// //方法2:
// //定义一个新数组,新建数组的长度比原有数组的长度少1个
// int[] newArr = new int[arr.length - 1];
// //采用将索引为5的替换索引为4的元素,而不新创建数组
// for (int i = 0; i < arr.length - 1; i++) {
// newArr[i] = arr[i];
// if(i >= 4){
// newArr[i] = arr[i + 1];
// }
// }
// //将新指针指向arr
// arr = newArr;
//换行
System.out.println();
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
}
}
案例3:
需求:
案例1:线性查找
定义数组:int[] arr1 = new int[]{34,54,3,2,65,7,34,5,76,34,67};
查找元素5是否在上述数组中出现过?如果出现,输出对应的索引值。
案例2:二分法查找
定义数组:int[] arr2 = new int[]{2,4,5,8,12,15,19,26,37,49,51,66,89,100};
查找元素5是否在上述数组中出现过?如果出现,输出对应的索引值。
代码1:二分法查找
package com.stguigu4.search_sort.exer2;
/**
* ClassName: BinarySearchTest
* Package: com.stguigu4.search_sort.exer2
* Description: 二分法查找
*
* 定义数组:int[] arr2 = new int[]{2,4,5,8,12,15,19,26,37,49,51,66,89,100};
* 查找元素5是否在上述数组中出现过?如果出现,输出对应的索引值。
*
* @Author 随心油条
* @Create 2024/1/26 11:22
* @Version 1.0
*/
public class BinarySearchTest {
public static void main(String[] args) {
//1.先定义初始化数组
int[] arr2 = new int[]{2,4,5,8,12,15,19,26,37,49,51,66,89,100};
int target = 5;
//定义一个小旗子
boolean isFlag = false;//判断是否找到了指定元素
int head = 0;
int end = arr2.length - 1;
int middle;
while (head <= end){
middle = (head + end)/2;
if(target == arr2[middle]){
System.out.println("恭喜你,找到了元素 " + target);
isFlag = true;
break;
} else if (target > arr2[middle]) {
head = middle + 1;
}else {//target < arr2[middle]
end = middle - 1;
}
}
if (!isFlag){
System.out.println("很遗憾,没有找到元素 " + target);
}
}
}
代码2:线性查找
package com.stguigu4.search_sort.exer2;
/**
* ClassName: LinearSearchTest
* Package: com.stguigu4.search_sort.exer2
* Description: 线性查找
*
* 定义数组:int[] arr1 = new int[]{34,54,3,2,65,7,34,5,76,34,67};
* 查找元素5是否在上述数组中出现过?如果出现,输出对应的索引值。
*
* @Author 随心油条
* @Create 2024/1/26 11:03
* @Version 1.0
*/
public class LinearSearchTest {
public static void main(String[] args) {
//定义、初始化数组
int[] arr1 = new int[]{34,54,3,2,65,7,34,5,76,34,67};
int target = 5;
target = 15;
//方法1:
//定义一个小旗子
boolean isFlag = false;
int i = 0;
for (; i < arr1.length; i++) {
if (arr1[i] == target){
isFlag = true;
break;
}
}
if (isFlag){
System.out.println("找到元素为" + target + ",其索引为:" + i); //输出找到元素为5,其索引为:7
}else{
System.out.println("没有找到为" + target + "的元素");
}
// //方法2:
// int i = 0;
// for (; i < arr1.length; i++) {
// if (arr1[i] == target){
// System.out.println("找到元素为" + target + ",其索引为:" + i); //输出找到元素为5,其索引为:7
// break;
// }
// }
// if (i == arr1.length){
// System.out.println("没有找到为" + target + "的元素");
// }
}
}
案例4:
需求:
案例1:使用冒泡排序,实现整型数组元素的排序操作
比如:int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67};
代码:
package com.stguigu4.search_sort.exer3;
/**
* ClassName: BubbleSortTest
* Package: com.stguigu4.search_sort.exer3
* Description: 案例:使用冒泡排序,实现整型数组元素的排序操作
*
* 比如:int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67};
*
* @Author 随心油条
* @Create 2024/1/26 14:30
* @Version 1.0
*/
public class BubbleSortTest {
public static void main(String[] args) {
int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67};
//先输出一下原数组
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
//实现冒泡功能
for (int j = 0; j < arr.length; j++) {
// for (int i = 0; i < arr.length - 1; i++) {//这样也可以,每一个数都比arr.length次
for (int i = 0; i < arr.length - 1 - j; i++) {//这种方法每轮可以少j次
if (arr[i] > arr[i + 1]){
//交换arr[i] 和 arr[i + 1]
int temp = arr[i];
temp = arr[i + 1];
arr[i + 1] = arr[i];
arr[i] = temp;
}
}
}
//排序好了之后在进行
System.out.println();//换行
//先输出一下原数组
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
}
}
案例5:
需求:
案例:使用快速排序,实现整型数组元素的排序操作
比如:int[] data = { 9, -16, 30, 23, -30, -49, 25, 21, 30 };
代码:
package com.stguigu4.search_sort.exer3;
/**
* 快速排序
* 通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分关键字小,
* 则分别对这两部分继续进行排序,直到整个序列有序。
*
* @author 尚硅谷-宋红康
* @create 13:18
*
*/
public class QuickSort {
public static void main(String[] args) {
int[] data = {9, -16, 30, 23, -30, -49, 25, 21, 30};
System.out.println("排序之前:");
for (int i = 0; i < data.length; i++) {
System.out.print(data[i]+" ");
}
quickSort(data);//调用实现快排的方法
System.out.println("\n排序之后:");
for (int i = 0; i < data.length; i++) {
System.out.print(data[i]+" ");
}
}
public static void quickSort(int[] data) {
subSort(data, 0, data.length - 1);
}
private static void subSort(int[] data, int start, int end) {
if (start < end) {
int base = data[start];
int low = start;
int high = end + 1;
while (true) {
while (low < end && data[++low] - base <= 0)
;
while (high > start && data[--high] - base >= 0)
;
if (low < high) {
//交换data数组[low]与[high]位置的元素
swap(data, low, high);
} else {
break;
}
}
//交换data数组[start]与[high]位置的元素
swap(data, start, high);
//经过代码[start, high)部分的元素 比[high, end]都小
//通过递归调用,对data数组[start, high-1]部分的元素重复刚才的过程
subSort(data, start, high - 1);
//通过递归调用,对data数组[high+1,end]部分的元素重复刚才的过程
subSort(data, high + 1, end);
}
}
private static void swap(int[] data, int i, int j) {
int temp = data[i];
data[i] = data[j];
data[j] = temp;
}
}
5.Arrays工具类的使用
基本语法的知识点:
数组工具类Arrays的使用 (熟悉)
1. Arrays类所在位置: 处在java.util包下
2. 作用:
java.util.Arrays类即为操作数组的工具类,包含了用来操作数组(比如排序和搜索)的各种方法。
案例1:
package com.stguigu5.arrays;
import java.util.Arrays;
/**
* ClassName: ArraysTest
* Package: com.stguigu5.arrays
* Description: 数组工具类Arrays的使用 (熟悉)
*
* 1. Arrays类所在位置: 处在java.util包下
*
* 2. 作用:
* java.util.Arrays类即为操作数组的工具类,包含了用来操作数组(比如排序和搜索)的各种方法。
*
* @Author 随心油条
* @Create 2024/1/26 15:17
* @Version 1.0
*/
public class ArraysTest {
public static void main(String[] args) {
//1. boolean equals(int[] a,int[] b): 比较两个数组的元素是否依次相等
int[] arr1 = new int[]{1,2,3,4,5};
int[] arr2 = new int[]{1,2,3,4,5};
// arr2 = new int[]{1,2,3,5,4};
System.out.println(arr1 == arr2);//false,这里是存什么比什么,存地址就比地址
boolean isEquals = Arrays.equals(arr1,arr2);//这里是调用Arrays.equals方法,比较arr1,arr2的内容是否相等
System.out.println(isEquals);//true
//2. String toString(int[] a):输出数组元素信息。
System.out.println(arr1);//输出arr1的地址,[I@776ec8df
System.out.println(Arrays.toString(arr1));//输出arr1中的元素[1, 2, 3, 4, 5]
//3. void fill(int[] a,int val):将指定值填充到数组之中。
Arrays.fill(arr1,10);
System.out.println(Arrays.toString(arr1));//输出[10, 10, 10, 10, 10]
//4. void sort(int[] a):使用快速排序算法实现的排序
int[] arr3 = new int[]{34,54,3,2,65,7,34,5,76,34,67};
Arrays.sort(arr3);//自动排序
System.out.println(Arrays.toString(arr3));//[2, 3, 5, 7, 34, 34, 34, 54, 65, 67, 76]
//5. int binarySearch(int[] a,int key):二分查找
//使用前提:当前数组必须是有序的
//方式1:
int index = Arrays.binarySearch(arr3,5);
System.out.println("元素5的索引为:" + index);//输出元素5的索引为2
//方式2:
int index1 = Arrays.binarySearch(arr3,15);
if(index1 >= 0){
System.out.println("找到了,索引值为:" + index1);
}else {
System.out.println("很遗憾,未找到该元素!");//输出很遗憾,未找到该元素!
}
}
}
6.数组中的常见异常
基本语法的知识点:
1. 数组的使用中常见的异常小结
> 数组角标越界的异常:ArrayIndexOutOfBoundsException
> 空指针的异常:NullPointerException
2. 出现异常会怎样?如何处理?
> 一旦程序执行中出现了异常,程序就会终止执行。
> 针对异常提供的信息,修改对应的代码,避免异常再次出现。
案例1:
package com.atguigu6.exception;
/**
* ClassName: ArrayExceptionTest
* Package: com.atguigu6.exception
* Description: 测试数组中常见的异常
*
* 1. 数组的使用中常见的异常小结
*
* > 数组角标越界的异常:ArrayIndexOutOfBoundsException
* > 空指针的异常:NullPointerException
*
*
* 2. 出现异常会怎样?如何处理?
* > 一旦程序执行中出现了异常,程序就会终止执行。
* > 针对异常提供的信息,修改对应的代码,避免异常再次出现。
*
* @Author 随心油条
* @Create 2024/1/26 15:52
* @Version 1.0
*/
public class ArrayExceptionTest {
public static void main(String[] args) {
//1. 数组角标越界的异常:
int[] arr = new int[10];
//角标的有效范围:0、1、2、...、9
// System.out.println(arr[10]);//报错:ArrayIndexOutOfBoundsException
// System.out.println(arr[-1]);//报错:ArrayIndexOutOfBoundsException
//2. 空指针异常:
//情况1:
int[] arr1 = new int[10];
arr1 = null;
// System.out.println(arr1[0]);//报错:NullPointerException
//情况2:
int[][] arr2 = new int[3][];
arr2[0] = new int[10];//此行代码不存在时,下一行代码就出现异常。
System.out.println(arr2[0][0]);//报错:NullPointerException
//情况3:
String[] arr3 = new String[4];//arr3是一个对象,当对象为null时,调用方法就报空指针的错
// System.out.println(arr3[0].toString());//报错:NullPointerException
}
}
二、企业真题
1. 数组有没有length()这个方法? String有没有length()这个方法?
数组没有length(),是length属性。
String有length()
2. 有数组int[] arr,用Java代码将数组元素顺序颠倒。
package com.atguigu3.common_algorithm.exer5;
/**
* ClassName: ArrayExer05
* Package: com.atguigu3.common_algorithm.exer5
* Description: 案例:元素反转,对称数组
*
* 定义数组:int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67};
* 如何实现数组元素的反转存储?你有几种方法。
*
* @Author 随心油条
* @Create 2024/1/25 21:55
* @Version 1.0
*/
public class ArrayExer05 {
public static void main(String[] args) {
//1. 定义数组:
int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67};
int temp;
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t"); //数组在转换之前输出一次,输出结果34 54 3 2 65 7 34 5 76 34 67
}
//方式1:(推荐)
// for (int i = 0; i < arr.length/2; i++) {
// 交互arr[i] 与 arr[arr.length - 1 - i]位置的元素
// temp = arr[i];
// arr[i] = arr[arr.length - 1 - i];
// arr[arr.length - 1 -i] = temp;
// }
//方式2:(推荐)
for (int i = 0, j = arr.length - 1 - i; i < j; i++, j--) {
//交互arr[i] 与 arr[j]位置的元素
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
// //方式3:(不建议,一,开辟一个新空间,二,遍历的次数太多)
// int[] newArray = new int[arr.length];
// for (int i = arr.length - 1; i >= 0; i--) {
// newArray[arr.length - 1 - i] = arr[i];
// }
// arr = newArray;
System.out.println();
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t"); //数组在转换之前输出一次,输出结果67 34 76 5 34 7 65 2 3 54 34
}
}
}
3. 为什么数组要从0开始编号,而不是1
数组的索引,表示了数组元素距离首地址的偏离量。因为第1个元素的地址与首地址相同,所以偏移量就是0。所以从0开始。
4. 数组有什么排序的方式,手写一下
冒泡。
package com.stguigu4.search_sort.exer3;
/**
* ClassName: BubbleSortTest
* Package: com.stguigu4.search_sort.exer3
* Description: 案例:使用冒泡排序,实现整型数组元素的排序操作
*
* 比如:int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67};
*
* @Author 随心油条
* @Create 2024/1/26 14:30
* @Version 1.0
*/
public class BubbleSortTest {
public static void main(String[] args) {
int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67};
//先输出一下原数组
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
//实现冒泡功能
for (int j = 0; j < arr.length; j++) {
// for (int i = 0; i < arr.length - 1; i++) {//这样也可以,每一个数都比arr.length次
for (int i = 0; i < arr.length - 1 - j; i++) {//这种方法每轮可以少j次
if (arr[i] > arr[i + 1]){
//交换arr[i] 和 arr[i + 1]
int temp = arr[i];
temp = arr[i + 1];
arr[i + 1] = arr[i];
arr[i] = temp;
}
}
}
//排序好了之后在进行
System.out.println();//换行
//先输出一下原数组
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
}
}
5. 常见排序算法,说下快排过程,时间复杂度?
快速排序(Quick Sort)由图灵奖
获得者Tony Hoare
发明,被列为20世纪十大算法之一
,是迄今为止所有内排序算法中速度最快的一种,快速排序的时间复杂度为O(nlog(n))。
快速排序通常明显比同为O(nlogn)的其他算法更快,因此常被采用,而且快排采用了分治法的思想,所以在很多笔试面试中能经常看到快排的影子。
排序思想:
- 从数列中挑出一个元素,称为"基准"(pivot)
- 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
- 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
- 递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。
6. 二分算法实现数组的查找
package com.stguigu4.search_sort.exer2;
/**
* ClassName: BinarySearchTest
* Package: com.stguigu4.search_sort.exer2
* Description: 二分法查找
*
* 定义数组:int[] arr2 = new int[]{2,4,5,8,12,15,19,26,37,49,51,66,89,100};
* 查找元素5是否在上述数组中出现过?如果出现,输出对应的索引值。
*
* @Author 随心油条
* @Create 2024/1/26 11:22
* @Version 1.0
*/
public class BinarySearchTest {
public static void main(String[] args) {
//1.先定义初始化数组
int[] arr2 = new int[]{2,4,5,8,12,15,19,26,37,49,51,66,89,100};
int target = 5;
//定义一个小旗子
boolean isFlag = false;//判断是否找到了指定元素
int head = 0;
int end = arr2.length - 1;
int middle;
while (head <= end){
middle = (head + end)/2;
if(target == arr2[middle]){
System.out.println("恭喜你,找到了元素 " + target);
isFlag = true;
break;
} else if (target > arr2[middle]) {
head = middle + 1;
}else {//target < arr2[middle]
end = middle - 1;
}
}
if (!isFlag){
System.out.println("很遗憾,没有找到元素 " + target);
}
}
}
7. 怎么求数组的最大子序列和
/*
* 输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
* 求所有子数组的和的最大值。要求时间复杂度为O(n)。
例如:输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,
因此输出为该子数组的和18。
*/
public class ArrDemo {
public static void main(String[] args) {
int[] arr = new int[]{1, -2, 3, 10, -4, 7, 2, -5};
int i = getGreatestSum(arr);
System.out.println(i);
}
public static int getGreatestSum(int[] arr){
int greatestSum = 0;
if(arr == null || arr.length == 0){
return 0;
}
int temp = greatestSum;
for(int i = 0;i < arr.length;i++){
temp += arr[i];
if(temp < 0){
temp = 0;
}
if(temp > greatestSum){
greatestSum = temp;
}
}
if(greatestSum == 0){
greatestSum = arr[0];
for(int i = 1;i < arr.length;i++){
if(greatestSum < arr[i]){
greatestSum = arr[i];
}
}
}
return greatestSum;
}
}