Java数组详解
为什么用数组?
现在需要录入计算机技术专业的26名同学的Java成绩,我们应该如何实现这个功能呢?
声明26个变量用于保存成绩?将成绩保存到数据库中?显然对于这种小的需求,这都不合适!此时我们便用到了数组!
什么是数组?
数组是有序的元素序列。若将有限个类型相同的变量的集合命名,那么这个名称为数组名。组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量。用于区分数组的各个元素的数字编号称为下标。数组是在程序设计中,为了处理方便, 把具有相同类型的若干元素按有序的形式组织起来的一种形式。这些有序排列的同类数据元素的集合称为数组。数组是用于储存多个相同类型数据的集合。
这个说法或许有些官方,也可以简单的将其理解为数组是用于保存多个相同类型数据的容器。
数组的特点:
◆只能存储同种类型数据
◆长度固定
◆存储数据类型可以基本数据类型 也可以时引用数据类型
◆数组存储是有序存储
◆下标就是元素的顺序标识 下标从0开始
数组的使用详解
使用数组的四个步骤。
➽第一步 声明数组 int [] a;
➽第二步 分配空间 a= new int[6];
➽第三步 对数组赋值 a[0] = 8;
➽第四步 对数组数据进行使用 a[0]=a[0]+5;
声明数组
声明格式:
数组类型[] 数组名;
➤➤➤➤ int num[];
或者都可以!!!!它俩实际上没有区别
数组类型 数组名[];
➤➤➤➤ int[] num;
//声明一个数组
int num[];
double[] score;
分配空间
分配格式:
数组名 = new 数据类型[大小] ;
注:数组都是引用数据类型
score = new int[26];
声明数组的同时进行空间分配
语法:
数据类型[ ] 数组名 = new 数据类型[大小] ;
//声明并分配空间
String[] name = new String[26]; //直接声明26个空间
赋值
下标 :数组的下标从0开始 比如 score[0]=87;
就是将score的第一个空间进行赋值
for循环赋值
//对数据进行赋值
Scanner scanner = new Scanner(System.in);
for(int i=0;i<score.length;i++) {//score.length用于计算数组的长度
System.out.println("请输入第"+(i+1)+"位同学的成绩:");
score[i] = scanner.nextDouble();
}
System.out.println("录入结束,共计录入了"+score.length+"名同学的成绩");
注: 数组变量.length用于计算数组的长度返回整数值 score.length
声明数组的同时分配空间和赋值
语法:
数据类型[ ] 数组名 ={};
int[] num= {10,20,30,66,80,9,4,6};//此时声明了一个长度为8的数组 并含有相应的数据
处理数据
for循环对数组数据进行使用
需求:录入成绩 并打印班级平均分和出每名同学的成绩
package com.qingsu.basis;
import java.util.Scanner;
public class Array {
public static void main(String[] arsg) {
//声明一个数组
double[] score; //成绩
//对数组进行分配空间
score = new double[26];
//对数据进行赋值
double sum=0;
Scanner scanner = new Scanner(System.in);
for(int i=0;i<score.length;i++) {
System.out.println("请输入第"+(i+1)+"位同学的成绩:");
score[i] = scanner.nextDouble();
sum = sum+score[i];
}
System.out.println("录入结束,共计录入了"+score.length+"名同学的成绩。平均成绩为:"+sum/score.length);
//使用数据
for(int j=0;j<score.length;j++) {
System.out.println("第"+(j+1)+"位同学的成绩为:"+score[j]);
}
}
}
//输出一组整数的最大值
package com.qingsu.basis;
import java.util.Scanner;
public class Array {
public static void main(String[] arsg) {
//声明数组并赋值
int[] num= {10,20,30,66,80,9,4,6};
int max=10;
for(int i=1;i<num.length;i++) {
if(num[i]>max) {
max=num[i];
}
}
System.out.println(max);
}
}
★另一种方式
//声明数组并赋值 冒泡排序前置 会改变原数组内数据的顺序
int[] num= {10,20,30,66,80,9,4,6};
int max=0;
for(int i=0;i<num.length-1;i++) {
if(num[i]>num[i+1]) {
max=num[i];
num[i]=num[i+1];
num[i+1]=max;
}
}
System.out.println(max);
数组的栈和堆
堆栈:在数据结构中,栈是一种可以实现"先进后出"
在这里不深入解释 栈和堆的概念 可以简单的理解为 new 所声明的数据在堆中 栈中保留了堆中数据的地址用于对数据的各种操作 储存方式如图
//直接打印数组变量名将会得到内存地址
double testNum[] = {5,6,78};
System.out.println(testNum);
数组的基础注意事项(数组越界、未分配空间、数组的声明赋值连用不可分割)
➧数组越界
当对数组的使用超出所声明的空间后会报出异常
错误示例:
//正常打印
int testArr[] = new int[5];
for(int i = 0;i<testArr.length;i++) {
testArr[i]=i;
System.out.println("testArr["+i+"]内的值为"+testArr[i]);
}
//越界报数组越界异常
package com.qingsu.basis;
import java.util.Scanner;
public class Array {
public static void main(String[] arsg) {
int testArr[] = new int[5];
for(int i = 0;i<testArr.length;i++) {
testArr[i]=i;
System.out.println("testArr["+i+"]内的值为"+testArr[i]);
}
System.out.println(testArr[5]);//testArr[5]超出了分配的范围
}
}
➧数组未分配空间
数组必须分配空间后才能使用 否则编译不通过
错误示例:
int testArr[];
testArr[5] = 10;
➧数组的声明赋值连用不可分割
数组的声明赋值连用语句是固定语句不可分割!!!
正确用法
int testArr[] = {154,45,55,33,99};
错误用法
//错误用法
int testArr2[] = new int[5];
testArr2 = {154,45,55,33,99};
int testArr3[];
testArr3 = {154,45,55,33,99};
forecah或者for增强
在Java中可以使用forecah对数组中的数据进行快速便利
语法:
for (数组类型(数组的数据类型) 变量名: 数组名 )
{
输出i就是遍历的每个元素
}
for增强只能适用于遍历 不能根据下标输出内容做判断、
使用示例
int num[] = {655,55,1,3,6645,52};
for (int i : num) {
System.out.println(i);//打印出数组的数据
}
double num2[] = {55.3,55.4,55.6,55.7,55.8};
for(double i : num2) {//变量类型要和数组的类型一致
System.out.println(i);
}
数组的维度
在Java中数组可以多维声明 那么什么是维度呢?
以二维为例 声明一个含有三个元素二维数组 等于声明了三个一维数组
在Java语言里提供了支持多维数组的语法,但如果从数组底层的运行机制上来看声明多维数组的实质便是一次性声明多个一维数组。
二维数组使用示例
二维数组的三种声明使用方式
第一种
//多个[]的使用即为多维数组 有几个[]即为几维数组
比如int num[][] = new int[3][3];
本质上是声明了三个数组长度为三的一维数组
在二维数组中 num.length 表示二维数组的长度 num[i].length表示一位数组的长度
因此我们可以使用for循环对数组进行使用 如以下示例
Scanner scanner = new Scanner(System.in);
//第一种
int num[][] = new int[3][3];//本质上是声明了三个数组长度为三的一维数组
for (int i = 0; i < num.length; i++) {
for (int j = 0; j < num[i].length; j++) {
System.out.println("请输入数据:");
num[i][j] = scanner.nextInt();
System.out.println(num[i][j]);
}
}
第二种
{}的嵌套可以直接对多维数组赋值 :int num1[][] = {{1,2,3,},{4,5,6},{7,8,9}};
//第二种
int num1[][] = {{1,2,3,},{4,5,6},{7,8,9}};
for (int j = 0; j < num1.length; j++) {
for (int k = 0; k < num1[j].length; k++) {
System.out.println(num1[j][k]);
}
}
第三种
二维数组的本质是声明多个一维数组
比如:int num2[][] = new int[3][];
本质便是声明了三个一维数组 分别为 num2[0],num2[1],num[2]
//第三种
int num2[][] = new int[3][];//可以直接声明一个不包含一维数组长度的二维数组
int num3[] = new int[5]; //声明一个数组长度为5的一维数组
int num4[] = {5,3,6};//声明一个含有数据的一位数组
num2[0] = num3; //num2[0] 本质是一个一位数组 可以直接将别的数组的空间分配给它
num2[1] = num4; //同样也可以直接将其他一维数组的空间和数组赋给它
num2[2] = new int[3];//可以进行正常的空间分配
数组使用示例
冒泡排序
需求 :将一组数据按照升序顺序排序
解决思路:
第一步:寻找最大值并将其放在最后面
第二步:将第一步寻找到的最大值去掉后继续第一步 (循环数组长度-1次)
第三步:完成排序
寻找最大值并将其放在最后面
int num[] = {3,2,0,5,4,1};
int centerNum = 0;//中间变量 用于存放较大的值
for (int j = 0; j< num.length-1; j++) {//将最大值放到数组的最后面
if(num[j]>num[j+1]) {
centerNum=num[j];
num[j] = num[j+1];
num[j+1] = centerNum;
}
}
第二步:将第一步寻找到的最大值去掉后继续第一步 (循环数组长度-1次)
for (int i = 0; i < num.length-1; i++) {//循环数组长度-1次
for (int j = 0; j< num.length-i-1; j++) {//每次结束后去掉已经找出的最大值
if(num[j]>num[j+1]) {
centerNum=num[j];
num[j] = num[j+1];
num[j+1] = centerNum;
}
}
}
冒泡排序实现
package com.qingsu.basis;
import java.util.Scanner;
public class Array {
public static void main(String[] arsg) {
//冒泡排序
int num[] = {3,2,0,5,4,1};
int centerNum = 0;//中间变量 用于存放较大的值
for (int i = 0; i < num.length-1; i++) {//循环数组长度-1次
for (int j = 0; j< num.length-i-1; j++) {//每次结束后去掉已经找出的最大值
if(num[j]>num[j+1]) {
centerNum=num[j];
num[j] = num[j+1];
num[j+1] = centerNum;
}
}
System.out.print("第"+(i+1)+"次数值比较排序结果:");
for (int k = 0; k < num.length; k++) {
System.out.print(num[k]+"\t");
}
System.out.println();
}
//分析 3,2,0,5,4,1
//第一次数值比较循环 比较5次 3>2 ==> 2 3 | 3>0 ==>2 0 3 | 3<5 ==>2 0 3 5 | 5>4 ==>2 0 3 4 5 | 5>1==>2 0 3 4 1 5
//2 0 3 4 1 5
//第二次数值比较循环 比较4次 2>0 ==> 0 2 | 2<3 ==>0 2 3 | 3<4 ==>0 2 3 4 | 4>1 ==>0 2 3 1 4 |
//0 2 3 1 4 5
//第三次数值比较循环 比较3次 0<2 ==> 0 2 | 2<3 ==>0 2 3 | 3>1 ==>0 2 1 3
//0 2 1 3 4 5
//第四次数值比较循环 比较2次 0<2 ==> 0 2 | 2>1 ==>1 2
//0 1 2 3 4 5
//第五次数值比较循环 比较1次 0<1 ==> 0 1
//0 1 2 3 4 5
System.out.print("最终排序结果:");
for (int i = 0; i < num.length; i++) {
int j = num[i];
System.out.print(num[i]+"\t");
}
}
}
打印台输出结果
分析 以{3,2,0,5,4,1}为例
初始数据 :3 2 0 5 4 1
进行第一次最大值寻找并置后循环 内层循环共比较5次
第一次比较:3>2 数组顺序交换后的结果 2 3 0 5 4 1
第二次比较:3>0 数组顺序交换后的结果 2 0 3 5 4 1
第三次比较:3<5 数组顺序不变后的结果 2 0 3 5 4 1
第四次比较:5>4 数组顺序交换后的结果 2 0 3 4 5 1
第五次比较:5>1 数组顺序交换后的结果 2 0 3 4 1 5
去掉第一次寻找的最大值5 进行第二次最大值并置后循环 内层循环共比较4次
第一次比较:2>0 数组顺序交换后的结果 0 2 3 4 1 (5)
第二次比较:2<3 数组顺序不变后的结果 0 2 3 4 1 (5)
第三次比较:3<4 数组顺序不变后的结果 0 2 3 4 1 (5)
第四次比较:4>1 数组顺序交换后的结果 0 2 3 1 4 (5)
去掉第二次寻找的最大值4 进行第三次最大值并置后循环 内层循环共比较3次
第一次比较:0<2 数组顺序不变后的结果 0 2 3 1 (4) (5)
第二次比较:2<3 数组顺序不变后的结果 0 2 3 1 (4) (5)
第三次比较:3>1 数组顺序交换后的结果 0 2 1 3 (4) (5)
去掉第三次寻找的最大值3 进行第四次最大值并置后循环 内层循环共比较2次
第一次比较:0<2 数组顺序不变后的结果 0 2 1 (3) (4) (5)
第二次比较:2>1 数组顺序交换后的结果 0 1 2 (3) (4) (5)
去掉第四次寻找的最大值2 进行第五次最大值并置后循环 内层循环共比较1次
第一次比较:0<1 数组顺序不变后的结果 0 1 (2) (3) (4) (5)
排序完成
外层循环数据
第1次:2 0 3 4 1 5
第2次:0 2 3 1 4 5
第3次:0 2 1 3 4 5
第4次:0 1 2 3 4 5
第5次:0 1 2 3 4 5
由上数据可知 冒泡排序每次的目标是寻找本次循环的最大值 并将其置后
排序算法
int temp;
for(int i=0;i<array.length-1;i++){//趟数
for(int j=0;j<array.length-i-1;j++){//比较次数
if(array[j]>array[j+1]){
temp=array[j];
array[j]=array[j+1];
array[j+1]=temp;
}
}
}
Java排序API
在现实开发中我们不会真的写一个排序算法进行排序 我们通常使用API进行数据的排序
比如 数据的升序
我们便使用Arrays.sort(num);
进行升序排序
package com.qingsu.basis;
import java.util.Arrays;
public class Array {
public static void main(String[] arsg) {
//排序API
int num[] = {655,55,1,3,6645,52};
Arrays.sort(num);
for (int i : num) {
System.out.println(i);
}
}
}