1.数组概述和定义格式说明
1.1一维数组
1.1.1 数组概念
数组是存储同一种数据类型多个元素的集合。也可以看成是一个容器。数组既可以存储基本数据类型,也可以存储引用数据类型。
1.1.2 数组定义格式
格式1: 数据类型[ ] 数组名;
格式2: 数据类型 数组名[ ];
举例:
int[] a; 定义了一个int类型的数组a;
int a[]; 定义了一个int类型的a数组;
1.1.3 数组的初始化
-
1.数组的初始化:Java中的数组必须先初始化,然后才能使用。
所谓初始化,就是为数组中的数组元素分配内存空间,并为每个数组元素赋值。 -
2.初始化的分类:
(1)动态初始化: 只指定长度,由系统给出初始化值。
(2)静态初始化: 给出初始化值,由系统决定长度 。
注意事项: 这两种方式,只能使用一种,不能进行动静结合 。 -
3.数组的动态初始化:
int[] arr=new int[3];
数据类型 [] 数组名=new 数组类型[数组长度];
每new一次都会在堆内存中开辟空间. -
4.数组的静态初始化:
由我们为数组元素赋值,由系统计算长度。
int[] arr = new int[]{ };
数据类型 [] 数组名=new 数组类型[]{数据};
静态初始化简写:int[] arr = { };
数据类型 [] 数组名={数据};
1.1.4 Java中的内存分配
1.Java虚拟机在执行Java程序的过程中会把它管理的内存划分成若干个不同的数据区域。下面是java虚拟机的内存管理图:
栈与堆存放变量的区别与说明 |
---|
栈:存放的局部变量。所谓局部变量是在方法中定义或者在方法声明上的变量。 |
堆:存放的是所有new出来的对象(数组也是对象) |
2.堆的特点:
(1)每一个new出来的东西都会为其分配一个地址值。
(2) 每一个变量都有一个默认的值
数据类型 | 默认值 |
---|---|
byte,short,int,long | 0 |
float,double | 0.0 |
char | ‘\u0000’(空格) |
boolean | false |
引用数据类型 | null |
(3) 使用完毕就变成了垃圾,等待垃圾回收器对其回收。
1.2 一维数组的内存图
1.2.1一个数组的动态初始化
class ArrayTest{
public static void main(String[] args) {
int[] arr=new int[3];
System.out.println(arr); //打印数组的地址值
arr[0]=10;
arr[1]=20;
arr[2]=30;
System.out.println(arr[0]);
}
}
1.2.2两个数组的动态初始化
class ArrayTest2 {
public static void main(String[] args) {
int[] arr=new int[3];
arr[0]=10;
arr[1]=20;
arr[2]=30;
int[] arr2=new int[2];
arr2[0]=100;
arr2[1]=200;
//输出数组的地址值
System.out.println(arr);
System.out.println(arr2);
//输出数组中的元素
System.out.println(arr[2]);
System.out.println(arr2[0]);
}
}
1.2.3三个数组的动态初始化
class ArrayTest3{
public static void main(String[] args) {
int[] arr1=new int[2];
arr1[0]=15;
arr1[1]=20;
int[] arr2=new int[2];
arr2[0]=33;
arr2[1]=89;
int[] arr3=arr1;
arr3[0]=500;
//输出数组的地址值
System.out.println(arr1); //
System.out.println(arr2); //
System.out.println(arr3); //
//判断两个数组的地址值是否相等
System.out.println(arr1==arr3);
//输出数组中的元素
System.out.println(arr1[0]); //
System.out.println(arr1[1]); //
System.out.println(arr2[0]); //
System.out.println(arr2[1]); //
System.out.println(arr3[0]); //
System.out.println(arr3[1]); //
}
}
1.2.4 一维数组的遍历
class Test1 {
public static void main(String[] args) {
int []arr={20,30,40,50,60,70};
//正向遍历数组
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
System.out.println("-----------------------");
//反向遍历数组
for (int length = arr.length-1; length >=0; length--) {
System.out.println(arr[length]);
}
}
}
2.一维数组的常见的算法
(1)数组获取最值(获取数组中的最大值或者最小值)
class ArrayTest1 {
public static void main(String[] args) {
int[] array = { 1,2,3,4,5 };
int maxIndex = 0;
int max = array[0];
int minIndex = 0;
int min = array[0];
for (int i = 0; i < array.length; i++) {
if (max < array[i]) {
max = array[i];
maxIndex = i;
}
}
for (int i = 0; i < array.length; i++) {
if (min>array[i]) {
min = array[i];
minIndex = i;
}
}
System.out.println("最大值是" + max + ",其下标为:" + maxIndex);
System.out.println("最小值是" + min + ",其下标为:" + minIndex);
}
}
(2)数组元素反转
思想:就是把元素对调
class ArrayTest2 {
public static void main(String[] args) {
int[] array = {1,2,3,4,5};
for (int i = 0; i < array.length / 2; i++) {
int temp = array[i];
array[i] = array[array.length - i - 1];
array[array.length - i - 1] = temp;
}
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
}
3.数组常见的两种异常:
数组有一个自带属性,叫做length属性,这个属性可以获取数组的长度。
(1)数组角标越界异常
在获取数组元素或给数组元素赋值,访问不存在的索引,就会出现数组角标越界异常。
(2)空指针异常
int[] arr={20,30,60};
arr=null;
System.out.println(arr[0]);
这是就会报错,空指针异常。
4.二维数组
4.1二维数组概述
(1)元素是一位数组的数组。数组里面套数组。
其实二维数组其实就是每一个元素为一维数组的数组。
(2)二维数组动态初始化:
int[][] arr=new int[3][2];
3代表的是二维数组的长度
2代表的是二维数组中一位数组的长度
System.out.println(arr[0]);//打印的是地址值,二维数组的第一个值是一个一位数组,所以打印的是一位数组的地址值。
(3)二维数组静态初始化:
由我们为元素赋值,由系统计算长度
int[][] arr2=new int[][]{{20,10},{20,30,4},{6.6.7}};
简写:int[][] arr2={{20,10},{20,30,4},{6.6.7}};
二维数组的其他定义语法:
int arr[][]=new int[3][2];
int[] arr[]=new int[3][2];
4.2二维数组的三种格式
(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]来获取
表示获取第m+1个一维数组的第n+1个元素
(2)二维数组格式2
数据类型[][] 变量名 = new 数据类型[m][];
m表示这个二维数组有多少个一维数组
这一次没有直接给出一维数组的元素个数,可以动态的给出。
举例:
int[][] arr = new int[3][];
arr[0] = new int[2];
arr[1] = new int[3];
arr[2] = new int[1];
(3)二维数组格式3
数据类型[][] 变量名 = new 数据类型[][]{{元素…},{元素…},{元素…}…};
简化版:
数据类型[][] 变量名 = {{元素…},{元素…},{元素…}};
这个格式属于静态初始化:由我们指定具体的元素值,由系统给分配长度
举例:
int[][] arr = {{1,2,3},{4,5,6},{7,8,9}};
int[][] arr = {{1,2,3},{5,6},{7}};
4.3二维数组的应用
(1)二维数组的遍历
public class MyTest {
public static void main(String[] args) {
//二维数组的遍历
int[][] arr = {{20, 1000}, {20, 30, 4}, {6, 6, 7}};
// int num=arr[0][0];
// int num2 = arr[0][1];
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.println(arr[i][j]);
}
}
}
}
(2)杨辉三角形:
需求:打印杨辉三角形(行数可以键盘录入)
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
public class MyTest3 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入行数");
int n = sc.nextInt(); //n=8
//定义二维数组,让行数和列数相同
int[][] arr = new int[n][n];
//先把首尾元素设置为1
for (int i = 0; i < arr.length; i++) {
arr[i][0] = 1;
arr[i][i] = 1;
}
//中间元素等会做
//外层循环控制行数,内层循环控制列数
for (int i = 2; i < arr.length; i++) {
for (int j = 1; j < i; 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();
}
}
}
5.传参问题
public class MyTest {
public static void main(String[] args) {
//定义两个 int 类型的变量
int a = 10;
int b = 20;
System.out.println("a: " + a + ",b: " + b);
//调用方法
change(a, b);
//输出a和的值
System.out.println("a: " + a + ",b: " + b);
//定义了一个数组
int[] arr = {1, 2, 3, 4, 5};
System.out.println("main定义的数组" + arr);
//调用方法
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) {
System.out.println("change方法中的" + arr);
//遍历数组,数组的元素如果是偶数就二倍
for (int x = 0; x < arr.length; x++) {
if (arr[x] % 2 == 0) {
arr[x] *= 2;
}
}
}
}
结果为:
注意:
调用方法时,传参有两种类型
基本类型作为参数传递,属于值传递,把值传过去,形参的改变,不影响实参。
引用类型作为参数传递,属于引用传递,传递的是地址值,形参的改变,会影响实参。