数组
1.数组:
数组既是引用数据类型,用来保存多个数据。也是一种线性表数据结构,它用一组连续的内存空间来存储具有相同类型的数据。(所谓数据结构,就是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。数据结构往往同高效的检索算法和索引技术有关)
1.1数组特性
- 内存中连续存储,并且下标从0开始(内存地址偏移)
- 数组长度一旦确定不能更改,也就是说数组不能添加和删除
- 查询和更改效率高,添加和删除效率低
- 数组都有内置属性length保存了数组长度,同时在java中有一个 java.util.Arrays 类提供了一些数组操作
1.2数组声明
静态声明:
在已知每个元素的时候,使用静态声明:
数据类型[] 变量名 = {值,值,值...} ; //简写
数据类型[] 变量名 = new 数据类型[]{值,值,值...}; //若是对数组进行二次赋值需要这样写
int[] arr = {1,2,3}; //简写声明
int[] arr;
arr = new int[] {1,2,3}; //二次赋值
动态声明:
不知道数组中每个元素的时候使用动态声明
数据类型[] 变量名 = new 数据类型[长度];
int[] arr = new int[5];
在动态声明中,保存的是对应类型的默认值,整数0;小数0.0;布尔型false;字符型 \u0000;引用型 null。
int[] arr;
arr = new int[3] ;
for(int i=0;i<3;i++){
System.out.print(arr[i]+" ");
}
以整型为例,输出如下
1.3存储方式
JVM内存分为五块,这里只画出三块,分别为
静态区/方法区:保存程序文件(class文件)以及静态数据,方法被调用之前也保存在静态区,内部还有运行时的常量池。
栈内存:执行方法的
堆内存:保存对象的
1.4数组使用
- 获取数据:
// 静态声明一个数组
int[] arr = { 1, 2, 3 };
// 获取: 数组名:[下标]
System.out.println("第二个元素是" + arr[1]);
// 数组长度: 数组名.length
System.out.println("数组长度是" + arr.length);
// 数组最后一个元素
System.out.println("最后一个元素是:" + arr[arr.length - 1]);
- 更改数据:
// 静态声明一个数组
int[] arr = { 1, 2, 3 };
//数组名[下标] = 值 ;
arr[1]=5;
System.out.print(arr[1]);
- 遍历:
// 静态声明一个数组
int[] arr = { 1, 2, 3 };
// 循环遍历数组
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
1.5常见异常:
1.下标越界
// 静态声明一个数组
int[] arr = { 1, 2, 3 };
// 访问第四个元素
System.out.print(arr[3]);
2.空指针
// 当数组为null时
int[] arr = null;
// 访问数组length属性
System.out.println(arr.length);
1.6数组传递
- 数组传参
int i = 1;
// 基本数据类型传参
m1(i);
m1(2);
int[] arr = { 1, 2, 3 };
// 数组传参
m2(arr);
// !数组字面量传参方式
m2(new int[] { 1, 2, 3 });
}
public static void m1(int i) {
}
public static void m2(int[] arr) {
}
- main方法传参
System.out.println(args[2]);
1.7传值和传址
传值:传递基本类型的数据,基本类型传递之后互相不影响,因为指向不同的空间
传址:传递引用数据类型的值,引用类型传递之后有影响,因为指向同一个堆内存对象空间
int i = 1;
m1(i);
System.out.println("main的i:" + i);
int[] arr = {1,2,3};
m2(arr);
System.out.println("main中arr的第一个元素值为:"+arr[0]);
}
public static int m1(int i) {
i = 10;
System.out.println("m1中的i:" + i);
return i;
}
public static void m2(int[] arr){
arr[0]=10;
System.out.println("m2中arr的第一个元素值为:"+arr[0]);
}
二维数组
1.声明方式:
静态声明:
数据类型[][] 变量名 = { { } } ;
int[][] arr ={{1,2,3},{4,5,6},{7,8,9}};
动态声明:
int[][] arr = new int[3][4]; //表示三个一维数组,每个一维数组里面有四个元素
int[][] arr = new int[3][]; //表示三个一维数组,且这三个一维数组都是null,这种需要单独初始化每一个一维数组的长度,一般用于每行列不一样。方法如下
arr[0]=new int[5];
System.out.println(arr[0].length);
2.存储方式:
int[][] arr = {{1,2},{3,4},{4,5}};
3.使用方式:
- 获取数据:
和一维数组类似
数组名[下标(一维数组)][下标(一维数组中元素)];
int[][] arr ={{1,2,3},{4,5,6},{7,8,9}};
System.out.println(arr[1][1]);
- 更改数据
//和一维数组类似,数组名[下标][下标]= 值:
int[][] arr ={{1,2,3},{4,5,6},{7,8,9}};
arr[1][1] =90;
System.out.println(arr[1][1]);
- 遍历
int[][] arr ={{1,2,3},{4,5,6},{7,8,9}};
for(int i =0;i<arr.length;i++){
for(int j=0;j<arr[i].length;j++){
System.out.print(arr[i][j]+" ");
}
System.out.println();
}
- 动态声明锯齿状
//二维表
int[][] arr = new int[3][4];
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
//锯齿状
int[][] arr = new int[4][];
// 遍历
for (int i = 0; i < arr.length; i++) {
arr[i] = new int[i + 1]; // 初始化每一个一维数组
for (int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
对于交换变量值的几种方法
1.中间变量:
int a=10,b=21,temp;
temp=a;
a=b;
b=temp;
2.位移运算:
x = 2; // 0000 0010
y = 3; // 0000 0011
// 转换为对应的二进制,每位异或,相同取0,不同取1,这里以八位举例
x = x ^ y; // 0000 0001
y = x ^ y; // 0000 0010
x = x ^ y; // 0000 0011
对于^(异或运算)有以下性质:
0^1=1,1^1=0:(即与1相异或结果为自己的按位取反)
归零率:A^A=0(即一个数与自己异或为0)
恒等率:A^0=A(即任何一个数与0异或之后还是本身)
交换律:A^B=B^A
结合律:A(^B^C)=(A^B)^C
自反:A^B^A=B