5.数组
1数组
1.1数组的定义
数组是一个相同类型的有序集合。数组是一种特殊的变量,一次性向计算机申请"一片"连续的空间。通过长度来控制要开辟多少个练习的空间;通过数据类型来控制每个空间的大小。
数组的元素:数组中保存的具体的值.
数组的长度:数组中能容纳最大的元素的个数。
数据下标:数组是通过下标表示保存位置的,数组的下标从0开始,最大下标为长度-1
注意:数组中的元素类型必须与声明数组时的数据类型相匹配。
数组元素索引必须是整型(常量、变量、表达式)
数组的存取:
赋值:数组名[下标]=值;
取值:数组名[下标];
特点:
1.数组的长度一旦声明指定后,无法更改
2.数组中的数据类型不能混合(数组中元素的数据类型不能混合存储)。
eg:public static void test1(){
数据类型[] 数组名=new 数据类型[长度];
int[] nums = new int[5];
为数组赋值: 数组名[下标]=值;
nums[0]=10;
//遍历
for(int i=0;i<5;i++){
System.out.println("nums["+i+"]="+nums[i]);
}
1.2数组的声明
数据类型[] 数组名;或 数据类型 数组名[];
eg: int nums[]; int[] nums;
数组在声明时并未分配空间,用 数据名.length 可以获取数组长度。
声明数组后初始化默认值:
int类型数组默认值为0
double类型数组默认值为0.0
boolean类型数组默认值false
1.3数组的初始化
1)声明数组
数据类型[] 数组名;
2)初始化(为数组分配空间)
数组名 =new 数据类型[长度];
eg: int[] nums;
nums=new int[5];
2 赋值
2.1动态初始化
数组的声明,初始化和赋值分开编写.
int[] nums;
nums=new int[4];
int[] nums=new int[4];
nums[0]=10;
...
2.2静态初始化
数组的声明,初始化和赋值一步完成。
数据类型[] 数组名={值1,值2....};
int[] nums ={1,2,3,4,5};
注意:不能指定长度,其长度取决于元素的个数。必须在编写在一行语句。
int[] nums;
nums={1,2,3,4,5};//错误写法。
int[]nums=new int[]{1,2,3,4,5};//正确
3 高级for循环(for-each)循环
高级for循环(for-each循环):JDK1.5以后的新特性。
语法:
for(元素的数据类型 变量名:数组或集合){
//循环体
}
执行过程:通过数组的下标将元素取出,并赋值给变量: int n = nums[i];
注意:元素的数据类型必须和数组的数据类型一致。
使用场景:功能略逊于for循环,在for-each无法直接使用数组的下标。主要用于遍历操作。
eg:
int[] nums = {10,20,30,40,50};
//方法一:通过数组下标进行遍历
for(int i=0;i<nums.length;i++){
int n = nums[i];
System.out.println(n);
}
System.out.println("*******************");
//方法二:使用for-each进行遍历
for(int n:nums){
System.out.println(n);
}
4 综合案例
根据用户输入的人数,动态创建数组,并获取用户输入的成绩,统计最高分,最低分和平均分
public static void main(String[] args){
double sum=0;//总成绩
double avg=0;//平均成绩
double max,min;//最高成绩和最低成绩
System.out.println("请输入班级人数:");
Scanner input = new Scanner(System.in);
int num = input.nextInt();//获取用户输入的人数
//创建数组用于保存学生成绩:数据类型[] 数组名 = new 数据类型[长度]
double[] scores = new double[num];//根据人数动态创建数组用于保存学生成绩
for(int i=0;i<scores.length;i++){
System.out.println("请输入第"+(i+1)+"个人的成绩:");
scores[i]=input.nextDouble();//获取学生成绩,并将其保存到数组中
}
max = scores[0]; //假设第一个人的成绩是最高分
min = scores[0]; //假设第一个人的成绩是最低分
//遍历
for(int i=0;i<scores.length;i++){
//System.out.println(scores[i]);
sum+=scores[i];//计算总成绩
if(scores[i]>max){
max = scores[i];
}
if(scores[i]<min){
min = scores[i];
}
}
avg = sum/scores.length;//计算平均成绩
System.out.println("最高分:"+max+",最低分:"+min+",平均分:"+avg);
}
5 数组的常用算法
5.1删除指定下标的元素
分析: 1.将指定下标index以后的元素向前移位
2.将数组的最后一个元素赋值为0(0为int类型数组元素的默认值)
public static void deleteElement(int[] arr,int index){
//删除前遍历输出
System.out.println("删除前数组元素为:");
for(int n:arr){
System.out.print(n+"\t");
}
System.out.println("");//换行
//将指定下标index以后的元素向前移位
for(int i=index;i<arr.length-1;i++){
arr[i]=arr[i+1];
}
//将数组的最后一个元素赋值为0
arr[arr.length-1]=0;
System.out.println("删除后数组元素为:");
for(int n:arr){
System.out.print(n+"\t");
}
}
5.2数组中删除指定的元素
分析:
1)根据元素的值获取该元素在数组中的下标位置
2)将指定下标index以后的元素向前移位
3)将数组的最后一个元素赋值为0(0为int类型数组元素的默认值)
public static void deleteElement2(int[] arr,int element){
int index=-1;//保存元素的下标位置
//删除前遍历输出
System.out.println("删除前数组元素为:");
for(int i=0;i<arr.length;i++){
//查找元素所在下标位置
if(element==arr[i]){
index=i;
}
System.out.print(arr[i]+"\t");
}
System.out.println("");//换行
//将指定下标index以后的元素向前移位
for(int i=index;i<arr.length-1;i++){
arr[i]=arr[i+1];
}
//将数组的最后一个元素赋值为0
arr[arr.length-1]=0;
System.out.println("删除后数组元素为:");
for(int n:arr){
System.out.print(n+"\t");
}
}
5.3 冒泡排序
原理:将相近的两个数字进行比较,大的向后去,小的向前赶。每比较一轮可以确定一个最大值。
冒泡排序口诀:
N个数字来排队,两两比较小靠前。
外层循环N-1(控制需要比较的轮数);
内层循环N-1-i(控制每轮需要比较的次数)。
eg:
public static void sort(int[] arr){
//外层循环:控制需要比较的轮数
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]){
int temp = arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
}
//遍历数组中元素并输出
public static void printArray(int[] arr){
for(int n:arr){
System.out.print(n+"\t");
}
System.out.println();
}
5.4查找元素
1)通过元素的遍历进行查找
在数组arr中查询target元素,如果元素存在返回其下标,否则返回-1。
public static int search(int[] arr,int target){
int index=-1;//要查找的元素的下标位置
//遍历
for(int i=0;i<arr.length;i++){
if(arr[i]==target){//比较
index=i;
break;
}
}
return index;
}
2)二分法查找
前提:待查找的数组必须是有序(大小顺序)
原理:将要查找元素与数组中的中间元素进行比较。
如果比中间元素值小,在左半边查找
如果比中间元素值大,在右半边查找
eg:
public static int binnarySearch(int[] arr,int ele){
int index=-1;//要查找的元素在数组中的下标位置
int left=0;//开始位置
int right=arr.length-1;//结束位置
int middle;//中间位置
while(left<=right){
middle=(left+right)/2;
if(arr[middle]==ele){
index=middle;
break;
}else if(arr[middle]>ele){//中间元素的值大于要查找的元素,在左半边查找
right = middle-1;
}else if(arr[middle]<ele){//中间元素的值小于要查找的元素,在右半边查找
left = middle+1;
}
}
return index;
}
6 java.util.Arrays工具类
API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。
在Java中除java.lang包下的类和接口可以直接使用之外,其他包下的类和接口在使用时,需要使用import关键字进行导包
java.util.Arrays类:提供了以下对数组操作的方法。
常用方法:
sort(int[] a) 对指定的 int 型数组按数字升序进行排序。
toString(int[] a) 返回指定数组内容的字符串表示形式(遍历)。
binarySearch(byte[] a, byte key)
binarySearch(int[] a, int key): 使用二分搜索法来搜索指定的 int 型数组,以获得指定的值。
fill(int[] a, int val) 将指定的 int 值分配给指定 int 型数组的每个元素(填充,用1替换所有元素)。
copyOf(int[] original, int newLength)复制指定的数组,截取或用 0 填充(如有必要),以使副本具有指定的长度。
copyOfRange(int[] original, int from, int to):将指定数组的指定范围复制到一个新数组。 包含起始位置但不包含结束位置。
....
访问静态方法(使用static修饰的方法):类名.方法名(..);进行调用。
7 命令行参数
作用:可以在执行java命令的过程中为main方法传递参数(值)。
用法:运行java命令时传入命令行参数: java 类名 "值1" "值2"...
注意:值1,值2..应该是字符串类型,命令行参数会将值1,值2...封装到args中传入给main方法,多个参数值之间用空格分割,下标从0开始
在获取命令行参数时需要注意下标不能越界,最大下标应该为参数的个数-1
8 可变参数
可变参数(...):从JDK1.5之后引入的新特性。
作用:避免因相同类型的参数个数不同而编写大量重载方法。
可变参数可以代表0或多个指定类型的参数。
可变参数只能作为方法的形参(在方法的定义时)使用,处理时可以将可变参数当作数组进行处理。
并且一个方法中最多只能有1个可变参数,位置必须放在参数的最后一个位置。
注意:调用带可变参数的方法时,数据类型必须与可变参数的类型相对应。
9 二维数组
定义:一个数组中每一个元素又是一个数组(数组嵌套数组)。
声明: 数据类型[][] 数组名 = new 数据类型[rows][cols];
eg:
int[][]nums=new int[3][2];
nums[0][0]=1;
nums[0][1]=2;
...
注意:二维数组声明时需要按照高纬度向低纬度的顺序指定。
int[][]nums = new int[3][];//合法
int[][]nums = new int[][3];//不合法
静态初始化:
int[][]nums={{1,2},{3,4},{5,6}};
int[][]nums={{1,2},{3,4},{5,6,7}};
int[][]nums;
nums={{1,2},{3,4},{5,6}};//错误
示例1:每个班级有3名同学,保存三个班级中的学生成绩,并计算平均分。
public static void test(){
int[][]scores = new int[3][3];
//使用循环获取学生信息
Scanner input = new Scanner(System.in);
for(int i=0;i<3;i++){
int sum=0;//班级的总成绩
System.out.println("请输入第"+(i+1)+"个班级的学生成绩:");
for(int j=0;j<3;j++){
scores[i][j]=input.nextInt();
sum+=scores[i][j];//计算总成绩
}
int avg = sum/3;//计算班级平均分;
System.out.println("第"+(i+1)+"个班级的平均分为:"+avg);
}
}
示例2:计算对角线之和:对角线上的元素i和j是相同; nums[0][0],nums[1][1],nums[2][2]
public static void test2(){
int[][] nums={{1,2,3},{4,5,6},{7,8,9}};
int sum=0;
for(int i=0;i<3;i++){
sum+=nums[i][i];
}
System.out.println("对角线之和为:"+sum);
}