数组的出现
现在遇到这样一个问题,随机定义100个范围在100以内的int型变量,并输出这100个变量的值。
如直接定义并输入的话,会容易把人累死,此时为了能更加便捷(绝对不是为了偷懒!!),出现了数组,现将两种情况做个对比:
第一种情况(非常不可取!!!):
int a1 = 10 , a2 = 20 , a3 = 30 ,a4 = 55 ,..... , a100 = 60;
System.out.println(a1);
System.out.println(a2);
。。。。。。。。。。
System.out.println(a100);
package Test;
import java.util.Random;
public class Dome5 {
public static void main(String[] args) {
int [] num = new int[100] ;
int num1 = 0;
for(int i = 0;i<100;i++) {//for循环实现数组的遍历
num1 = new Random().nextInt(100);//获取100以内的随机数
num[i] = num1; //将随机到的数存储到数组第i个位置
System.out.println(num[i]);//将数组的第i位数输出
}
}
}
Java 数组的定义与声明
如上所示,数组的类型是多种多样的,可以是int,double,char等基本数据类型,也可以存储实例化对象等引用数据类型,因为数组本身属于引用数据类型,所以声明一个数组时需要实例化,有三种数组实例化方式:
- 数组动态初始化,如例题,其格式为:
数据类型 [] 数组名 = new 数据类型[数组长度];
int [] num = new int [100];
- 数组静态初始化定义,格式如下:
简化格式:数据类型 [] 数组名 = {值1,值2…};
int [] num = {1,5,7,3} 完整格式:数据类型 [] 数组名 = new 数据类型[]{值1,值2....}
- 先声明数组,需要时根据需求申请开辟空间:
int [] num = null ; num = new int[8];
char [] num = null ;num = new char[]{'a','b'};
有几个值得注意的点:
1.数组下标是由0开始的,也就是说以下数组:
int [] a = new int[2]
它的长度为2(有2个空间)分别是a[0],a[1],如果输出a[2]的话会提示数组越界异常。所以遍历时要从第0位开始输出。
2.每个数组声明完成后,数组中的每个空间都有默认值,默认值为它的数据类型(int–>0,char–>null…)
3.lengh方法可以获取数组长度,格式为:数组名.lengh
可以用int类型变量接收数组长度。
数组的优势与局限
- 优势:按照索引遍历数组方便快捷,查询速度快。
- 局限:存储类型单一,存储空间固定,按内容查询慢
数组的扩容
先看例子:
int [] a = new int[2];
int [] b = new int[1];
b=a;
System.out.println(b.length);//运行结果为2
将数组A赋值给数组B时:B=A,是将A直接指向B,使得B的空间大小、数据与A保持一致,只有同一类型的数组可以互相拷贝
此时学会了将一个数组进行扩容:
package Test;
public class Dome6 {
public static void main(String[] args) {
int [] a = new int[3] ;//定义一个长度为3的数组
int [] b = new int[a.length+1];//定义一个长度比数组a长度还大1的数组
for(int i = 0;i<a.length;i++) {
b[i] = a[i];//将a的所有元素赋值给b对应的空间
}
b[b.length-1] = 9;//此时给b的最后一位添加新元素
a = b;//再将b指向a
for(int i :a) {//遍历数组a后发现a的长度扩大了1,并被赋值为9
System.out.println(i);
}
}
}
Arrays工具类的使用
Arrays工具类中提供了一个方法,copyOf()方法,示例:
package Test;
import java.util.Arrays;
public class Dome7 {
public static void main(String[] args) {
//第一种全部拷贝
int [] arr = {2,5,8,4, 6};
int [] a = Arrays.copyOf(arr, arr.length+1);//参数1:源数组;参数2:目标数组长度
for(int i:a) {
System.out.print(i);
}//结果:将数组arr拷贝到数组a中,a的长度为arr长度加1
System.out.println();
//第二种指定位置拷贝
int [] arrnew = new int[10];//目标拷贝地址
//参数1:源数组;参数2:源数组的起始拷贝位置;参数3:目标地址;参数4:目标地址的起始拷贝位置;参数5:拷贝数量
System.arraycopy(arr, 0, arrnew, 2, 5);
for(int i :arrnew) {
System.out.print(i);
}
}
}
运行结果:
数组的遍历
- 传统的for型循环遍历
通过for型循环将数组的每个元素打印一遍,使用起来比较灵活。
int [] arr = {1,2,5,4,6,3,8,7};
for(int i = 0 ;i < arr.length;i++){
System.out.println(arr[i]);
}
- foreach遍历(没有用foreach而是for是为了避免因为引入新的关键字,造成兼容性方面的问题)
将每个元素都给i赋值一次,再打印出i,整体结构更为简单直观
int [] arr = {2,3,5,4,8,9,7,1};
for(int i:arr){
System.out.println(i);
}
数组元素的选择排序
原理:双层循环,
第一层:每次循环找到最大的数将其从大到小排列。
第二层:每次循环都是将当前位置的元素与其他元素做一次比较,并把当前比较结果中最大元素放到当前位置
示例:
package Test;
import java.util.Arrays;
public class Dome8 {
public static void main(String[] args) {
int [] arr = {1,2,3,4,5,6,7,8,9};//定义数组并赋值
for(int i = 0;i<arr.length;i++) {
for (int j = i+1; j < arr.length; j++) {//永远是第i位与i位后面的数作比较
if (arr[i]<arr[j]) {//如果i位小,则将两个数做一个调换,将大的元素放到i位
int n = arr[i];
arr[i] = arr[j];
arr[j] = n;
}
}
System.out.println(Arrays.toString(arr));//用tostring方法直接打印数组
}
}
}
它的排序过程是这样的:
数组元素的冒泡法排序
原理:两层循环,将所有元素两两比较,大的沉下去,小的浮上来
package Test;
import java.util.Arrays;
public class Dome8 {
public static void main(String[] args) {
int[] a= {9,8,7,6,5,4,3,2,1};
for(int i=0;i<a.length-1;i++) {
for (int j = 0; j < a.length-i-1; j++) {
if(a[j]>a[j+1]) {//将目前的元素与后一位元素作比较
int temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
System.out.println(Arrays.toString(a));
}
}
}
它的排序过程是这样的:
多维数组
提出问题:如何存储一个年级中每个班的学生姓名
思路:如果给每个班都定义一个数组,用来存储本班学生姓名的话,太过繁琐,可以用二维数组来解决,用两种元素控制,班级,个人。同样存储全校学生的话可以用三维数组解决:年纪,班级,个人
- 定义:
二维数组:int [] [] a = new int [2] [3];
,数组元素个数为23,(相当于有2个班,每班3个学生,存储姓名的话可以用String类型)
三维数组:int [] [] [] a = new int [2] [3] [2]
,数组元素个数为23*2(相当于有2个年级,有3个班,每班2个学生,存储姓名的话可以用String类型) - 遍历:将数组中每部分的每个元素(二维数组两层for循环,三维数组三层for循环)分别打印输出
int [] [] a = new int [2] [3];
for(int i = 0;i<a.length;i++){
for(int j = 0;j<a[i].length;j++){
System.out.println(a[i][j]);
}
}