小爪给绿帽子分配了任务:有10个表示身高的变量,获取最大值;有10个表示年龄的变量,获取最大值
绿帽子:这简单!
小爪:那就交给你了,抓紧完成
......
小爪:这就是你的方案?要是有100个变量怎么办?我真想用我80米的大砍刀砍死你......
int a1 = 10;
int a2 = 20;
int a3 = 12;
int a4 = 5;
int a5 = 30;
int a6 = 23;
// 存储最大值
int temp = 0;
if(a1 > a2) {
temp = a1;
}else {
temp = a2;
}
if(temp < a3) {
temp = a3;
}
if(temp < a4) {
temp = a4;
}
if(temp < a5) {
temp = a5;
}
if(temp < a6) {
temp = a6;
}
System.out.println(temp);
1 数组的基本用法
数组是用来存储一组相同类型数据的数据结构,数组中的数据在内存中是连续存储的,数组属于引用类型
1)数组4要素
数组名称:合法的标识符,用来区分不同的数组
数组元素:数组中存放的数据,可以是指定的任何一种数据类型,且所有数据类型相同
元素下标:也称索引,数组中每个数据的编号,从0开始,用于访问某个具体位置的元素
元素类型:声明数组时指定的数据类型
2)2个注意点
数组中元素类型必须相同
数组一旦创建,长度不可改变,但是数组中的各个元素的值可以被改变
1.1 数组的声明
基本语法:
// 推荐写法
数据类型[] 数组变量名;
或者
数据类型 数组变量名[];
int a[];
String[] b;
double c[];
// 错误写法
int a[5];
注意:Java声明数组时不能指定其长度(数组中元素的个数),而需要在数组的创建阶段来指定。
1.2 数组的初始化
1)静态初始化
在数组声明的同时,对数组元素分配内存空间并对其赋值
int[] arr = {100, 4, 56, 89, 12};
String[] nameArr = new String[]{"haha", "lisi", "san", "hehe"};
数组的长度由大扩号中元素的个数决定,长度不可改变
元素的值由程序员指定,系统不自动赋值
2)动态初始化
显式指定数组的长度,而不指定数组元素的值。
int[] arr = new int[6];
数组的长度在数组创建时显式指定
数组元素的值如果没有指定,则由系统自动赋默认值
// 默认值0
int[] a = new int[5];
System.out.println(a[0]);
// 默认值0.0
double[] d = new double[5];
System.out.println(d[1]);
// 默认值0.0
float[] f = new float[5];
System.out.println(f[1]);
// 默认值\u0000
char c[] = new char[4];
System.out.println(c[1]);
// 默认值0
short[] s = new short[5];
System.out.println(s[0]);
// 默认值false
boolean[] bb = new boolean[5];
System.out.println(bb[1]);
// 默认值null
String[] ss = new String[3];
System.out.println(ss[0]);
int[] arr = new int[4];
arr[0] = 1;
arr[1] = 10;
arr[2] = 100;
// 下标越界
arr[3] = 1000;
数组长度也可以通过变量赋值
int len = 10;
int[] arr = new int[len];
System.out.println(arr.length);
1.3 数组的访问
数组在声明,创建(内存中为之分配空间)后,就可以访问数组中的每个元素
1)通过下标访问当个元素
语法:arrayName[index]
index 为数组元素下标(索引),可以是整型常量或整型表达式。如a[3], b[i], c[6*i]
2)普通循环遍历访问
循环访问每个元素
int[] arr = {23, 45, 12, 6, 36};
for(int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
数组的length属性可以获取它的长度,例如:arr.length
索引值从0开始,且必须小于数组的长度,即0~n-1,否则发生数组越界异常
3)增强for循环
也可称作foreach循环
基本语法:
for(元素类型 名称 : 数组名/集合等) {
}
int[] arr = {23, 45, 12, 6, 36};
for(int item : arr) {
System.out.println(item);
}
2 数组的排序
2.1 冒泡排序
原理:针对待排序的元素,从第一个元素开始,相邻的两个元素依次进行比较,选出最小或最大的元素,放在序列的结束位置
比如,我们针对待排序数据进行升序排序
第一轮比较如图所示:
第一次,23和15比较,23>15,交换
第二次,23和8比较,23>8,交换
第三次,23和34比较,23<34,不交换
第四次,34和20比较,34>20,交换
第一轮比较结束,34放到序列的最后
依此类推,再对剩余的待排序元素进行比较,5个元素经过总共四轮比较,最终可以得到升序的排序结果:
8 | 15 | 20 | 23 | 34 |
---|---|---|---|---|
public void bubbleSort(int[] arr) {
int temp = 0;//交换时使用的临时变量
if((arr == null) || (arr.length == 0)) {
return;
}
//外层循环决定比较的轮数
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]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
2.2 选择排序
原理:根据升序或者降序的需求,每次从待排序的元素中选出最小或最大的元素,放在序列的起始位置。
选择排序时,排序的轮数和比较的次数与待排序的元素个数相关
比如待排序的元素如下arr: 23 42 5 17 35,我们进行升序排序
使用变量index记录最小值元素的索引
1)第一轮比较:index=0
Arr[0]和42比较 ,23<42,index=0
Arr[0]和5比较,23>5,index=2
Arr[2]和17比较,5<17,index=2
Arr[2]和35比较,5<35,index=2
比较4次,找到最小值5所在索引2,将5和23交换位置
第一轮比较结束:5 42 23 17 35
红色表示待排序元素
2)第二轮比较:
Index=1
Arr[1]和23比较 ,23<42,index=2
Arr[2]和17比较,23>17,index=3
Arr[3]和35比较,17<35,index=3
比较3次,找到最小值17所在索引3,将17和42交换位置
第二轮比较结束:5 17 23 42 35
3)第三轮比较:
Index=2
Arr[2]和42比较 ,23<42,index=2
Arr[2]和35比较,23<35,index=2
比较2次,本轮不用交换
第二轮比较结束:5 17 23 42 35
4)第四轮比较:
Index=3
Arr[3]和35比较 ,42<35,index=4
比较1次,42和35交换位置
第四轮比较结束:5 17 23 35 42
四轮过后,整个比较结束,得到最终排序结果
public void selectSort(int[] arr) {
int index=0;//最小值元素的下标
int temp = 0;//交换时使用的临时变量
if((arr == null) || (arr.length == 0)) {
return;
}
//外层循环决定比较的轮数
for(int i=0; i < arr.length - 1; i++) {
index=i;
//内层循环决定每轮比较的次数
for(int j = i + 1; j < arr.length; j++) {
//在无序区中找到最小数据并保存其数组下标
if(arr[j] < arr[index]) {
index = j;
}
}
//将最小元素与本轮循环的首元素进行交换
temp = arr[i];
arr[i] = arr[index];
arr[index] = temp;
}
}
3 二维数组(了解)
数组的每个元素仍然是数组
3.1 初始化
1)动态初始化
int[][] a = new int[4][5]; // 4行5列
int[][] b = new int[2][]; // 注意:此时b[0]元素为空
b[0] = new int[6];
2)静态初始化
int[][] a = {{1}, {1, 2, 4}, {56, 6}}; // 每行的元素个数可以不同
int[][] b = new int[][]{{1, 4}, {5}};
3.2 二维数组的访问
int [][] arr = new int[][]{{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.println(arr[i][j]);
}
}
4 方法的可变参数
定义方法时,当形参个数不固定时(0-n个),可以使用可变参数来解决。
可变参数使用“…”实现,Java 编译器将可变参数转换成数组
处理可变参数必须放在形参列表的最后,它前面可以有一些其他形式的参数
返回值 方法名(参数类型... 参数名) {
}
public static void main(String[] args) {
add();
add(12);
add(12, 13);
int[] arr = {1, 3, 6};
add(arr);
}
public static void add(int... nums) {
int result = 0;
/*
for (int v : nums) {
result += v;
}
*/
for(int i = 0; i < nums.length; i++) {
result += nums[i];
}
System.out.println(result);
}
附录
引用数据类型
基础类型的变量,在内存中,存储的是常量值
引用类型变量,在内存中存储的值比较特殊,这个值是对象的地址
值传递和引用传递
值传递和引用传递是针对方法调用时,参数的传递情况
值传递:是将实参的值复制一份给形参,形参的值相当于实参的一个副本,形参(副本)的值被改变,不会影响原来实参的值。基础类型属于值传递。
可以将值传递理解成文件的负复印,不管如何修改复印件,都不会对原件产生影响
引用传递:本质上,也是将实参的值复制一份给形参,只不过这个值比较特殊,是引用类型的对象的地址。通过形参对对象进行操作,会改变原来对象的值。
可以将引用传递理解成信用卡的副卡,主卡和副卡都可以消费同一个信用卡的money