Java数组、变量交换、Scanner使用
数组
数组概述和特性
数组是引用数据类型,是一个院子底层的数据结构,并且几乎在任何语言中,都是最基础的数据结构,数组又被称为索引数组。
- 数组中的元素类型必须一致,意味着空间大小一致。
- 数组在内存中是连续的内存空间,也就意味着,找到一个就能找到其他所有的元素
- 默认使用第一个空间作为整个数组的地址,然后通过偏移量,找到其他元素。
- 偏移量为0就代表第一个元素,偏移量为1就代表第二个元素,以偏移量确定数据所在的位置,所以数组的下标从零开始。像这种通过内存地址直寻法查找效率极高
- 因为能够快速找到某个元素,所以想要更改某个元素的时候,只需要使用 = 赋值即可。所以数组查询和更改效率极高
- 数组一旦确定,长度不能更改,想要提那家或者删除元素,必须新建数组,然后把原数组中需要保留的元素,以及新插入的元素依次复制到新数组中,效率较低。
- 数组特性:查询更改块,添加删除慢。
- 总结:
①数组是引用数据类型,会占用两块内存空间,栈内存一块,堆内存一块,栈内存保存的是堆内存数组对象的地址。
②数组是一种线性连续存储的数据结构
③数组就是一个容器,用来存储其他数据。数组可以存储任意元素,不过每一维元素类型必须一致(数组可以多维)。
④数组长度一旦确定,不可更改。数组中默认有个length属性,用来保存数组的元素。
⑤数组下标从零开始
⑥数组查询更改快,添加删除慢
数组声明
- 静态声明:预先知道数组中的每位元素分别是什么。
语法结构:数据类型[] 变量名= {类型值1,类型值2,…};
如:
int i = 1;
int[] is = {1,2,3};
int[][] iss = { {1,2,3}, {1,2,3}, {1,2,3}};
int[][][] isss = {{ {1,2,3}, {1,2,3}, {1,2,3}},{ {1,2,3}, {1,2,3}, {1,2,3}},{ {1,2,3}, {1,2,3}, {1,2,3}}};
- 动态声明:预先不知道数组中每位元素分别是什么,不过需要确定数组类型以及长度,先用对应的类型默认值占位。
语法结构:数据类型[] 变量名 = new 数据类型[长度];
如:
int[] is = new int[5];
int[][] iss = new int[5][2];
int[][][] isss = new int[3][5][2];
数组的遍历和使用
- 获取数据
数组变量名[下标];
int[] arr = {1,2,3,4,5};
System.out.println("arr数组的第三个元素是:"+arr[2]);
- 设置数据
数组名[下标] = 值;
int[] arr = new int[3];
int[1] = 3;
System.out.println("arr数组的第二个元素是:"+arr[1]);
- 遍历数组
增强for循环:把数组中每一位元素拿出来,赋值给 变量。
语法结构:
for(数据类型 变量 : 数组 ){
数组操作
}
如:
//获取数组长度:数组名.length
for(int i = 0;i < arr.length;i++){
System.out.pring(arr[i]);
}
//增强for循环
for(int i:arr){
System.out.pring(i);
}
数组常见异常
- 下标越界:java.lang.SrrIndexOutOfBoundsException
解释:使用数组下标超过数组的长度,下标从零开始,比如:
int[] arr = new int[2];
System.out.println(arr[2]);
- 空指针异常:java,lang.NullPointerException
解释:使用null值,访问属性,因为是null,并没有指向堆内存数组空间,所以在堆中找不到对象,自然没有办法操作数组属性。比如:
int[] arr = null;
System.out.println(arr[0]);
数组传递
- 先声明数组后传递
int[] arr = {1,2,3};
//m1是方法名
m1(arr);
- 动态声明数组传递
//m1是方法名
m1(new int[3]);
- 静态声明方式传递
//m1是方法名
m1(new int[]{1,2,3,4});
main方法传参
二维数组
声明方式
- 静态:如:
int[][] arr = {
{1,2,3},
{1,2}
};
- 动态:如:定义一个三行五列的表格
解释:二维数组中有三个一维数组,每一个一维数组有五个元素。
int[][] arr = new int[3][5];
存储方式
栈中保存二维数组在堆中的地址,堆中每一个一维数组保存每一行数组的地址。
获取数据
变量[下标][下标]
如:
int[][] arr = {
{1,2,3},
{1,2}
};
System.out.println(arr[0][0]);
System.out.println(arr[length-1][arr[length-1].length-1]);
遍历二维数组
如:
int[][] arr = {
{1,2,3},
{1,2}
};
//for循环遍历
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.println(arr[i][j]);
}
}
//增强for循环遍历
for (int[] is : arr) {
for (int i : is) {
System.out.println(i);
}
}
动态设置二维数组中一维数组元素个数
如:
int[][] arr = new int[5][];
for (int i = 0; i < arr.length; i++) {
arr[i] = new int[i+1];
}
for (int[] is : arr) {
for (int i : is) {
System.out.print(i);
}
System.out.println();
}
/*
0
00
000
0000
00000
*/
传值和传引用的区别
- 传值 : 指的是基本类型传递
- 传引用 : 指的是引用类型的传递
- 传值之后,如果在对应方法中将值更该,不会影响调用处的值
- 如果是传引用,被调用方法通过引用,把内存中数据更改的话,调用处再次通过地址找到空间后,值就发生更改了。
如:
public static void main(String[] args){
int i = 10;
m1(i);
System.out.println("main+++++++"+i);
int[] a = new int[5];
for (int j : a) {
System.out.print(j);
}
System.out.println();
m1(a);
for (int j : a) {
System.out.print(j);
}
}
public static void m1(int i){
i++;
System.out.println("m1+++++++++"+i);
}
public static void m1(int[] i){
i[1]++;
}
/*
输出结果为:
m1+++++++++11
main+++++++10
00000
01000
*/
Scanner工具类
Scanner接受用户命令
System.in标准输入
//创建对象并设置标准输入
Scanner sc = new Scanner(System.in);
System.out.println("请输入:");
//程序执行到这里就会等待用户输入
//多个数据以空格隔开,next只会获取一个数据,如果有多个空格隔开的数据只能读取第一个
String s1 = sc.next();
//获取一行数据
String s2 = sc.nextLine();
//获取整数
int a = sc.nextInt();
//获取小数
int b = sc.nextDouble();
交换变量的值
借助中间变量
如:
int x = 10;
int y = 20;
int temp = x;
x = y;
y = temp;
加减运算
如:
int x = 10;
int y = 20;
a = a + b;
b = a - b;
a = a - b;
移位运算交换
如:
int m = 2;//0010
int n = 3;//0011
m = m ^ n;//0001 = 0010 ^ 0011
n = m ^ n;//0010 = 0001 ^ 0011
m = m ^ n;//0011 = 0001 ^ 0010