数组
概念:数组是存储同一种数据类型多个元素的集合。也可以看成是一个容器。数组既可以存储基本数据类型,也可以存储引用数据类型
定义格式:
格式一:数据类型[] 数组名;
格式二:数据类型 数组名[];
举例:
int[ ] a; //定义了一个int类型的数组a;
int a[ ]; //定义了一个int类型的数组a;
一、数组的初始化
Java中数组必须先初始化才能使用,即为数组中的元素分配内存空间并赋值
初始化的分类:
(1)动态初始化: 只指定长度,由系统给出初始化值
(2)静态初始化: 给出初始化值,由系统决定长度
注意:两种初始化方式只能使用一种,不能动静结合
(一)、动态初始化
格式:数据类型[] 数组名 = new 数据类型[数组长度];
举例:int[] arr = new int[3]; //定义了一个int类型的数组arr,这个数组可以存放3个int类型的值。
- Java中的内存分配以及栈和堆的区别
栈: 存放的是局部变量
局部变量:在方法定义中或者方法声明上的变量都是局部变量。
堆: 存放的是所有new出来的东西
特点:
a: 每一个new出来的东西都会为其分配一个地制值。
b: 每一个变量都有一个默认的值
byte,short,int,long – 0
float,double – 0.0
char – ‘\u0000’
boolean – false
引用数据类型 – null
c: 使用完毕就变成了垃圾,等待垃圾回收器对其回收
C:方法区:(面向对象部分讲解)
D:本地方法区:(和系统相关)
E:寄存器:(cpu使用)
- Java中一个数组的内存图解
-
Java中两个数组的内存图解
-
Java三个引用两个数组图解
执行流程:
定义第一个数组,定义完毕后,给数组元素赋值。赋值完毕后,再输出数组名称和元素
定义第二个数组,定义完毕后,给数组元素赋值。赋值完毕后,再输出数组名称和元素
定义第三个数组,把第一个数组的地址值赋值给它。(注意类型一致),通过第三个数组的名称去把元素重新赋值
最后,再次输出第一个数组数组名称和元素
(二)、静态初始化及内存图
格式:数据类型[] 数组名 = new 数据类型[]{元素1,元素2,…};
举例: int[] arr = new int[]{1,2,3};
简化格式:数据类型[] 数组名 = {元素1,元素2,…};
举例: int[] arr = {1,2,3};
1 public class ArrayDemo03 {
2 public static void main(String[] args) {
3 int[] arr = { 1, 2, 3, 4 }; // 静态初始化
4 // 下面的代码是依次访问数组中的元素
5 System.out.println("arr[0] = " + arr[0]);
6 System.out.println("arr[1] = " + arr[1]);
7 System.out.println("arr[2] = " + arr[2]);
8 System.out.println("arr[3] = " + arr[3]);
9 }
10 }
上述代码中采用静态初始化的方式为数组每个元素赋予初值,分别是1、2、3、4。需要注意的是,第3行代码千万不可写成int[] arr = new int[4]{1,2,3,4};,这样写编译器会报错
二、数组操作的两个常见小问题越界和空指针
- ArrayIndexOutOfBoundsException:数组索引越界异常
每个数组的索引都有一个范围,即0~length-1。在访问数组的元素时,索引不能超出这个范围,否则程序会报错,如下所示。ArrayDemo06.java
1 public class ArrayDemo06 {
2 public static void main(String[] args) {
3 int[] arr = new int[4]; // 定义一个长度为4的数组
4 System.out.println("arr[0]=" + arr[4]); // 通过角标4访问数组元素
5 }
6 }
运行结果如下图所示
上图运行结果中所提示的错误信息是数组越界异常ArrayIndexOutOfBoundsException,出现这个异常的原因是数组的长度为4,其索引范围为0~3,而上述代码中的第4行代码使用索引4来访问元素时超出了数组的索引范围。
- NullPointerException:空指针异常
在使用变量引用一个数组时,变量必须指向一个有效的数组对象,如果该变量的值为null,则意味着没有指向任何数组,此时通过该变量访问数组的元素会出现空指针异常
public class ArrayDemo2 {
public static void main(String[] args) {
int[] arr = new int[]{10, 20};
arr = null;// 人为置空
//NullPointerException 空指针异常
int length = arr.length;
System.out.println(length);
}
}
运行结果如下图所示
三、数组常用操作
1、数组的遍历
public static void main(String[] args) {
int[] arr={10,20,50,40,102};
//数组的遍历
for(int i=0;i<arr.length;i++){
System.out.println(arr[i]);
}
}
2、数组获取最值
public static void main(String[] args) {
//获取数组中的最大值或最小值
int[] arr = {10, 20, 50, 40, 102};
int max = getMax(arr);
System.out.println("最大值是" + max);
}
public static int getMax(int[] arr){
int max = arr[0];
for(int i = 1; i<arr.length; i++){
if(arr[i]>arr[0]){
max = arr[i];
}
}
return max;
}
3、数组反转
public class ArrayDemo3 {
public static void main(String[] args) {
//数组元素反转(就是把元素对调)
int[] arr = {10, 20, 30, 40, 50}; //50 40 30 20 10
for (int i = 0, j = arr.length - 1; i < j; i++, j--) {
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
reverseArray(arr);
showArray(arr);
}
//数组元素反转
private static void reverseArray(int[] arr) {
//分析:首尾元素值交换,遍历一半
for (int i = 0; i < arr.length / 2; i++) {
//采用中间变量进行值交换
int t = arr[i];
arr[i] = arr[arr.length - 1 - i];
arr[arr.length - 1 - i] = t;
}
}
//遍历数组
private static void showArray(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + ",");
}
}
}
4、数组查表法
根据键盘录入索引,查找对应星期
import java.util.Scanner;
public class ArrayDemo8 {
public static void main(String[] args) {
//数组查表法(根据键盘录入索引, 查找对应星期)
//根据索引查元素
String[] arr = {"星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"};
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个整数 1----7");
int index = scanner.nextInt();
String str = getElementByArray(index, arr);
System.out.println(str);
}
private static String getElementByArray(int index, String[] arr) {
if (index >= 1 && index <= 7) {
return arr[index - 1];
} else {
return "查无此元素";
}
}
}
5、数组基本查找
查找指定元素第一次在数组中出现的索引
import java.util.Scanner;
public class ArrayDemo9 {
public static void main(String[] args) {
//根据元素查索引
String[] arr = {"星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"};
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个星期");
String str = scanner.nextLine();//获取用户输入的字符串
int index = getIndex(str, arr);
System.out.println("该元素的索引是" + index);
}
private static int getIndex(String str, String[] arr) {
//遍历数组
for (int i = 0; i < arr.length; i++) {
if (str.equals(arr[i])) {
return i;
}
}
return -1; // 一般喜欢用 -1 代表没找到
}
}
二维数组
概念:二维数组其实就是每一个元素为一维数组的数组
定义格式:
数据类型[][] 变量名 = new 数据类型[m][n]
m表示这个二维数组有多少个一维数组 必须写上
n表示每一个一维数组的元素个数 可不写
举例:
int[][] arr = new int[3][2];
表示定义了一个二维数组arr,这个二维数组有3个一维数组,名称是arr[0],arr[1],arr[2],每个一维数组有2个元素,可以通过arr[m][n]来获取
注意事项:
(1)以下格式也可以表示二维数组:
数据类型 数组名[] [] = new 数据类型[m] [n];
数据类型[] 数组名[] = new 数据类型[m] [n];
(2)int[] x,y[]; //定义了两个数组 一个是一维数组x= new int[3],另一个是二维数组y=new int[3] []
-
二维数组的内存图
-
二维数组遍历
public static void main(String[] args) { int[][] arr = {{2, 4}, {10, 30}, {10, 30, 40}, {10, 1}}; //二维数组的遍历 for (int i = 0; i < arr.length; i++) { //System.out.println(arr[i]); //一维数组 for (int j = 0; j < arr[i].length; j++) { System.out.println(arr[i][j]); } } }
-
打印杨辉三角
public class ArrayDemo { public static void main(String[] args) { //B: //需求:打印杨辉三角形(行数可以键盘录入) // //1 //1 1 //1 2 1 //1 3 3 1 //1 4 6 4 1 //1 5 10 10 5 1 // /** * 分析规律: * 1.每一行的第一个数和最后一个数都是1 * 2.从第三行开始,中间的数等于我上一行的前一列的数和我上一行本列的数之和 */ Scanner sc = new Scanner(System.in); System.out.println("请输入行数"); int n = sc.nextInt(); //1.第一个数和最后一个数都是1 //2.第三行开始,中间的数等于我上一行的前一列的数和我上一行本列的数之和 int[][] arr=new int[n][n]; //定义一个数组,行列数都一样 for (int i = 0; i < arr.length; i++) { arr[i][0]=1; //将每一行的第一个数,置成1 arr[i][i]=1; //将三角形的每一行的最后一个元素置成1 } //计算中间元素 for (int i =2; i < arr.length; i++) { for (int j =1; j <= i-1; j++) { //第三行开始,中间的数等于我上一行的前一列的数和我上一行本列的数之和 arr[i][j]=arr[i-1][j-1]+arr[i-1][j]; } } //遍历二维数组 for (int i = 0; i < arr.length; i++) { for (int j = 0; j <=i; j++) { System.out.print(arr[i][j]+"\t"); } System.out.println(); } } }
Java中的参数传递问题
看程序写结果,并画内存图解释
public static void main(String[] args) {
int a = 10;
int b = 20;
System.out.println("a: " + a + ",b: " + b);
change(a,b);
System.out.println("a: " + a + ",b: " + b);
int[] arr = {1,2,3,4,5};
change(arr);
System.out.println(arr[1]);
}
public static void change(int a,int b) {
System.out.println("a: " + a + ",b: " + b);
a = b;
b = a + b;
System.out.println("a: " + a + ",b: " + b);
}
public static void change(int[] arr){
for(int x = 0 ; x < arr.length ; x++){
if(arr[x]%2 == 0){
arr[x] *= 2;
}
}
}
输出结果:
a: 10,b: 20
a: 10,b: 20
a: 20,b: 40
a: 10,b: 20
4
内存图:
递归
-
思想体现
-
内存图
-
斐波那契数列
案例:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问第二十个月的兔子对数为多少?
由此可见兔子对象的数据是:1 , 1 , 2 , 3 , 5 , 8 …
public class MyTest2 {
public static void main(String[] args) {
// 1 1 2 3 5 8 13 21 从第三个数开始,这个数等于前两个数之和 (斐波那契数列)
//递归来做
int sum = sumRabbit(20);
System.out.println("兔子的对数" + sum);
}
private static int sumRabbit(int i) {
if (i == 1 || i == 2) {
return 1;
} else {
return sumRabbit(i - 1) + sumRabbit(i - 2);
}
}
}