Java基础语法5
1 数组的概述
1.1 数组的理解-重点
数组(Array),是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。
1.2 相关的概念-重点
- 数组名
- 元素
- 下标(或索引)
- 数组的长度
1.3 数组的特点
- 数组是有序排列的
- 数组属于引用数据类型的变量。数组的元素,既可以是基本数据类型,也可以是引用数据类型
- 创建数组对象会在内存中开辟一整块连续的空间
- 数组的长度一旦确定,就不能修改。
1.4 数组的分类
- 按照维数:一维数组、二维数组、。。。
- 按照数组元素的类型:基本数据类型元素的数组、引用数据类型元素的数组
2 一维数组
2.1 声明和初始化
语法格式
type var[]
或者type[] var
例如:
int a[];
int[] a1;
double b[];
String[] c; //引用类型变量数组
初始化
- 静态初始化:在定义数组的同时就为数组元素分配空间并赋值
- 动态初始化:数组声明且为数组元素分配空间与赋值的操作分开进行
//声明
int[] ids;
//1.1静态初始化:数组的初始化和数组元素的赋值操作同时进行
ids = new int[]{1001,1002,1003,1004};
//1.2动态初始化:数组的初始化和数组元素的赋值操作分开进行
String[] names = new String[5];//引用数据类型4个字节 4*5=20
names[0]="管树林";//赋值
2.2 获取指定位置的元素
通过下标获取(下标从0开始,到数组的长度-1结束)
语法格式
数组名[下标]
//格式:数组名[下标]
int[] ids = new int[]{1001,1002,1003,1004};
System.out.println(ids[1]);
2.3 获取数组的长度
通过length属性获取
int[] ids = new int[]{1001,1002,1003,1004};
System.out.println(ids.length);
2.4 如何遍历数组
int[] ids = new int[]{1001,1002,1003,1004};
for(int i = 0;i < ids.length;i++){
System.out.println(ids[i]);
}
2.5 元素默认初始化值-重点
-
数组元素是整型(byte、int、long、short):`0`
-
数组元素是浮点型:`0.0`
-
数组元素是char型:`0`或`'\u0000'`(ASCll是0的字符),而非`'0'`
-
数组元素是boolean型:`false`
-
数组元素是引用数据类型:`null`
2.6 数组的内存解析-重点
2.6.1 内存概述
内存是计算机中的重要原件,临时存储区域,作用是运行程序。我们编写的程序是存放在硬盘中的,在硬盘中的程序是不会运行的,必须放进内存中才能运行,运行完毕后会清空内存。
Java虚拟机要运行程序,必须要对内存进行空间的分配和管理。
2.6.2 Java虚拟机的内存划分
为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
区域名称 | 作用 |
---|---|
栈区 | 方法运行时使用的内存,比如main方法运行,进入方法栈中执行。 |
堆区 | 存储对象或者数组,new来创建的,都存储在堆内存。 |
方法区 | 分为常量池 和静态区 ,用于存储常量及字节码文件(简单理解成.class文件) |
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AOlV5kdg-1605359538255)(.\assets\堆栈.png)]
课堂练习:
从键盘读入学生成绩,找出最高分,并输出学生成绩等级。
成绩 >= 最高分 - 10 等级为A;
成绩 >= 最高分 - 20 等级为B;
成绩 >= 最高分 - 30 等级为C;
其余 等级为D;
提示:先读入学生人数,根据人数创建int数组,存放学生成绩。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e3dHX69E-1605359538259)(./images/lianxi.png)]
3 数组与方法
之前的方法中我们学习了方法的参数和返回值,但是使用的都是基本数据类型。那么作为引用类型的数组能否作为方法的参数进行传递呢,当然是可以的。
3.1 数组作为方法参数
数组作为方法参数传递,传递的参数是数组内存的地址。
public static void main(String[] args) {
int[] arr = { 1, 3, 5, 7, 9 };
//调用方法,传递数组
printArray(arr);
}
/* 创建方法,方法接收数组类型的参数 进行数组的遍历 */
public static void printArray(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UUVPAjg2-1605359538262)(.\assets\数组参数.png)]
3.2 数组作为方法返回值
数组作为方法的返回值,返回的是数组的内存地址
public static void main(String[] args) {
//调用方法,接收数组的返回值
//接收到的是数组的内存地址
int[] arr = getArray();
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
/*
创建方法,返回值是数组类型 return返回数组的地址
*/
public static int[] getArray() {
//数组静态初始化数组
//int[] arr=new int[]{1,3,5,7,9};
//数组静态初始化数组-简写
int[] arr = { 1, 3, 5, 7, 9 }; //需要的要素:类型、长度、初始化数据
//返回数组的地址,返回到调用者
//reture new int[]{1,3,5,7,9};
return arr; //reture可以返回需要返回的数据并结束该方法
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3WCCm9iy-1605359538265)(.\assets\数组返回值.png)]
3.3 方法的参数类型区别
- 分析下列程序代码,计算输出结果。
public static void main(String[] args) {
int a = 1; int b = 2;
System.out.println(a); //1
System.out.println(b); //2
change(a, b);
System.out.println(a); //a
System.out.println(b); //b
}
public static void change(int a,int b) {
int tem=a;
a=b;
b=tem;
}
//看下回放
- 分析下列程序代码,计算输出结果。
public static void main(String[] args) {
int[] arr = {1,3,5};
System.out.println(arr[0]); //1
change(arr);
System.out.println(arr[0]);//200
}
public static void change(int[] arr) {
arr[0] = 200;
}
-
总结:
在Java中的赋值都是值传递,没有引用传递(被传值的地址)
- 方法的参数为基本类型时,传递的是数据值。
- 方法的参数为引用类型时,传递的是地址值。
4 二维数组
Java 语言里提供了支持多维数组的语法。
如果说可以把一维数组当成几何中的线性图形,那么二维数组就相当于是一个表格。
对于二维数组的理解,我们可以看成是一维数组array1又作为另一个一维数组array2的元素而存在。其实,从数组底层的运行机制来看,其实没有多维数组。
4.1 声明和初始化
4.1.1 动态初始化-数据个数固定
语法格式1
int[][] arr = new int[3][2]; 3*2*4 = 24
定义了名称为arr的二维数组
二维数组中有3个一维数组
每一个一维数组中有2个元素
一维数组的名称分别为arr[0], arr[1], arr[2]
给第一个一维数组1脚标位赋值为78写法是:arr[0][1] = 78;
语法格式2
int[][] arr = new int[3][]; 3 * 4(地址)
二维数组中有3个一维数组。
每个一维数组都是默认初始化值null (注意:区别于格式1)
可以对这个三个一维数组分别进行初始化
arr[0] = new int[3]; arr[1] = new int[1]; arr[2] = new int[2];
4.1.3 静态初始化-比较灵活
语法格式
int[][] arr = new int[][]{{3,8,2},{2,7},{9,0,1,6}};
定义一个名称为arr的二维数组,二维数组中有三个一维数组
每一个一维数组中具体元素也都已初始化
第一个一维数组 arr[0] = {3,8,2};
第二个一维数组 arr[1] = {2,7};
第三个一维数组 arr[2] = {9,0,1,6};
第三个一维数组的长度表示方式:arr[2].length;
注意:
-
特殊写法情况:int[] x,y[]; x是一维数组,y是二维数组。
-
Java中多维数组不必都是规则矩阵形式
4.2 内存解析-重点
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GYtgCcHk-1605359538267)(.\assets\二维数组的内存解析1.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r1LCpCg0-1605359538268)(.\assets\二维数组的内存解析2.png)]
4.3 获取指定位置的元素
语法格式
数组名[下标][下标]
//数组名[下标][下标]
int[] arr[] = new int[][]{{1,2,3},{4,5,9,10},{6,7,8}};
System.out.println(arr[0][1]);
4.4 遍历二维数组
int[] arr[] = new int[][]{{1,2,3},{4,5,9,10},{6,7,8}};
for(int i = 0;i < arr.length;i++){
for(int j = 0;j < arr[i].length;j++){
System.out.print(arr4[i][j] + " ");
}
System.out.println();
}
课堂练习1
使用二维数组的方式求下列表格中所有数字的和。
package day03;
public class text {
public static void main(String[] args) {
int arr[][] = new int[][]{{3,5,8},{12,9},{7,10,6,4}};
int sum=0;
for(int i=0;i <arr.length ; i++){
for(int j = 0;j < arr[i].length;j++){
sum+=arr[i][j];
}
}
System.out.println("表格中的数字和为:"+sum);
}
}
3 | 5 | 8 | |
---|---|---|---|
12 | 9 | ||
7 | 10 | 6 | 4 |
课堂练习2
声明:
int[] x,y[];
等价于
int[] x;
int[][] y;
在给x,y变量赋值以后,以下选项允许通过编译的是:
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;//不行
x [I@0x1234
y [[I@0x1234
5 数组常见算法-理解
5.1 赋值
典型案例-作业
使用二维数组打印一个 10 行杨辉三角(由二项式组成的)。
【提示】
1. 第一行有 1 个元素, 第 n 行有 n 个元素
2. 每一行的第一个元素和最后一个元素都是 1
3. 从第三行开始, 对于非第一个元素和最后一个元素的元素。即:yanghui[i][j] = yanghui[i-1][j-1] + yanghui[i-1][j];
public class text {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt(); //输入行数
// 二维数组来实现行列
int[][] yanghui = new int[n][];
//初始化
for (int i = 0; i<yanghui.length;i++){
// 每行的个数是所在行数加一
yanghui[i] = new int[i+1];
for(int j = 0;j<yanghui[i].length;j++){
yanghui[i][0]=1; //第一个数是1
yanghui[i][yanghui[i].length-1] = 1; // 最后一个数也是1
if(i > 1 && j > 0 && j < i){
//第三行开始,第二个数开始,但不到最后一个数
yanghui[i][j] = yanghui[i-1][j]+yanghui[i-1][j-1];
}
}
}
//遍历,打印
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();
}
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2GKkDkR7-1605359538269)(.\assets\timg.jpg)]
5.2 求值
典型案例
定义一个int型的一维数组,包含10个元素,分别赋一些随机整数,然后求出所有元素的最大值,最小值,和值,平均值,并输出出来。
要求:所有随机数都是两位数。
public class text {
public static void main(String[] args) {
int[] arr=new int[10];
for (int i = 0; i < arr.length; i++) {
arr[i]=(int)(Math.random()*(99-10+1)+10);
System.out.print(arr[i]+"\t");
}
System.out.println();
int maxValue=arr[0];
for (int i = 0; i < arr.length; i++) {
if (maxValue<arr[i]) {
maxValue=arr[i];
}
}
System.out.println("最大值为"+maxValue);
int minValue=arr[0];
for (int i = 0; i < arr.length; i++) {
if (minValue>arr[i]) {
minValue=arr[i];
}
}
System.out.println("最小值为"+minValue);
int sum=0;
for (int i = 0; i < arr.length; i++) {
sum+=arr[i];
}
System.out.println("总和为"+sum);
double avgValue=sum/arr.length;
System.out.println("平均值为"+avgValue);
}
}
5.3 反转
示例代码
//方法一:交换
for(int i = 0;i < arr.length / 2;i++){
String temp = arr[i];
arr[i] = arr[arr.length - i -1];
arr[arr.length - i -1] = temp;
}
//方法二:定义两个指针,再交换
for(int i = 0,j = arr.length - 1;i < j;i++,j--){
String temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
5.4 查找
- 线性查找
典型案例
String dest = "BB";
dest = "CC";
boolean isFlag = true;
for(int i = 0;i < arr.length;i++){
if(dest.equals(arr[i])){
System.out.println("找到了指定的元素,位置为:" + i);
isFlag = false;
break;
}
}
if(isFlag){
System.out.println("很遗憾,没有找到的啦!");
}
- 二分法查找
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z1JQEV3R-1605359538270)(./images/二分法.png)]
//前提:所要查找的数组必须有序。
int[] arr = new int[]{-98,-34,2,34,54,66,79,105,210,333};
int dest = -34;
int head = 0;//初始的首索引
int end = arr.length - 1;//初始的末索引
boolean isFlag = true;
while(head <= end){
int middle = (head + end)/2;
if(dest == arr[middle]){
System.out.println("找到了指定的元素,位置为:" + middle);
isFlag = false;
break;
}else if(arr[middle] > dest){
end = middle - 1;
}else{//arr[middle] < dest
head = middle + 1;
}
}
if(isFlag){
System.out.println("很遗憾,没有找到的啦!");
}
int binFind(int[] arr,int dest)// 找到返回下标,没有找到返回-1
5.5 排序(冒泡)
冒泡排序
冒泡排序的原理非常简单,它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。
排序思想
-
比较相邻的元素。如果第一个比第二个大(升序),就交换他们两个。
-
对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
-
针对所有的元素重复以上的步骤,除了最后一个。
-
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较为止。
int[] arr = new int[]{43,32,76,-98,0,64,33,-21,32,99};
//冒泡排序
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]){
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
sort(int[] arr)
sort(int[] arr,int i)// i 1升序 2降序
6 Arrays工具类-重点(运用)
java.util.Arrays类即为操作数组的工具类,包含了用来操作数组(比如排序和搜索)的各种方法。
打开查看常用方法的声明(源码)
- 常用方法
序号 | 方法定义 | 方法作用 |
---|---|---|
1 | boolean equals(int[] a, int[] b) | 判断两个数组是否相等 |
2 | String toString(int[] a) | 输出数组信息 |
3 | void fill(int[] a, int[] val) | 将指定值填充到数组之中 |
4 | void sort(int[] a) | 对数组进行排序 |
5 | int binarySearch(int[] a, int key) | 对排序后的数组进行二分法检索指定的值 |
6 | copyof(数组,长度) | 复制数组(长度小就取前几个,大就补0) |
7 | deepEquals(数组1,数组2) | 深度判断是否相等 |
8 | stream() | 极大值、极小值、和等 |
排序案例
// java.util.Arrays类的sort()方法提供了数组元素排序功能:
public static void main(String[] args) {
int [] numbers = {5,900,1,5,77,30,64,700};
Arrays.sort(numbers);
for(int i = 0; i < numbers.length; i++){
System.out.println(numbers[i]);
}
}
7 数组常见异常
7.1 下标越界
- 异常名称:
ArrayIndexOutOfBoundsException
示例代码
int[] arr = new int[2];
System.out.println(arr[2]);
System.out.println(arr[-1]);
7.2 空指针
异常名称:NullPointerException
示例代码
int[] arr = null;
System.out.println(arr[0]);
//arr引用没有指向实体,却在操作实体中的元素时。
//情况一:
int[] arr1 = new int[]{1,2,3};
arr1 = null;
System.out.println(arr1[0]);
//情况二:
int[][] arr2 = new int[4][];
System.out.println(arr2[0][0]);
//情况三:
String[] arr3 = new String[]{"AA","BB","CC"};
arr3[0] = null;
System.out.println(arr3[0].toString());