java基础知识
六、数组
- 简介
- 概念:具有相同数据类型的组合,或者相同的数据类型的集合,但此集合非比集合,别把数学中的那些全部搬过来,什么并集、补集、交集的,在这里不合适啊😄
- [a, b, c ]
- 0 1 2 索引(数组下标)
- 下标开始与
0索引
,终止于数组名.length-1
6.1.一维数组
-
创建(声明数组)
- 第一种:int arr[];
- 第二种:int []arr;
-
指定长度:int a[]=new int[3];
- 创建数组并指定长度
- 声明并分配内存空间,但并未进行赋值
- 指定长度[ ]里面可以是一个结果为整型的表达式,
int a[]=new int[3*5];
- 指定长度也可以为
0
,但无实际意义
-
数组的初始化(赋值)
-
int a[]=new int[3];
//定义一个数组,并指定长度
a[0]=7;
a[1]=8;
a[2]=10;//分别对每个元素进行初始化
-
int b[ ]=new int[ ]{4,5,6};
//未指定长度,随便,赋值多少,长度在再来计算
//使用new关键字创建数组时,如果是int型数组,其缺省值为0
-
-
内存中的数组
-
数组下标不可以越界(超出数组长度)
-
创建数组时,若指定了长度,不可以在创建数组的同时进行赋值,必须分别赋值
-
获取数组长度:使用
数组名.length
package 第六章_数组;
public class T1一维数组 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
//数组定义:相同类型数据的集合
@SuppressWarnings("unused")
int a1[];//创建数组方法1
@SuppressWarnings("unused")
int []a2;//创建数组方法2
@SuppressWarnings("unused")
int a3[]={1,2,3};
//创建一个int型的数组,并赋予三个初值,故长度=3
int a4[]=new int[2];//创建一个长度为2的数组
a4[0]=24;
a4[1]=25;
//对数组a4进行初始化
/*a4[2]=26;
System.out.println(a4);
Exception in thread "main" java.lang.ArrayIndexOutOf
BoundsException: Index 2 out of bounds for length 2
at 第六章_数组.T1一维数组.main(T1一维数组.java:14)
a4[2]下标2越界,因为数组长度=2,根本就没有a4[2]的存在,虽然编写不报错,
但运行报错*/
@SuppressWarnings("unused")
int a5[]=new int [5];
//int a5[]=new int [5]= {1,2,3,4,5};语法错误指定长度不可以直接赋值
//@SuppressWarnings("unused")
int a51[]=new int []{1,2,3,4,5};
System.out.println("数组a51的长度:\n"+a51.length);//获取a51数组长度
//int a6[]=new int[2*5.5];2*5.5不可以从double转换为int
int a6[]=new int[10+5];
//不夸精度前提下,长度可以用公式表达
System.out.println("数组a6长度:\n"+a6.length);
int day[]= {31,28,31,30,31,30,31,31,30,31,30,31};
for(int i=0;i<day.length;i++) {
//for的第个参数,使用.length更加方便,尤其是数组长度大情况下
System.out.println((i+1)+"月有多少天?\n"+day[i]+"天");
//不用用i++或者++i,会错位
}
}
}
运行结果:
数组a51的长度:
5
数组a6长度:
15
1月有多少天?
31天
2月有多少天?
28天
3月有多少天?
31天
4月有多少天?
30天
5月有多少天?
31天
6月有多少天?
30天
7月有多少天?
31天
8月有多少天?
31天
9月有多少天?
30天
10月有多少天?
31天
11月有多少天?
30天
12月有多少天?
31天
6.2.二维数组
-
创建
数组元素类型 数组名[ ][ ] 数组元素类型 [ ][ ] 数组名 int arr[ ][ ]=new int [行][列];
-
初始化
对于整型二维数组,成功创建之后,都会为每个元素赋予初始值 0
-
内存空间
-
形状:不一定是矩形
-
遍历二维数组:使用双for或者foreach语句
-
使用foreach时,化二维为一维,然后分别遍历
package 第六章_数组; public class T2二维数组 { public static void main(String[] args) { // TODO 自动生成的方法存根 int arr[][];//创建二维数组 int [][]arr1;//创建二维数组 //二维数组初始化 int arr2[][]= {{1,2,3},{4,5,6}};//方法1 //第一行1,2,3 第二行 4,5,6 System.out.println("行数"+arr2.length); //arr2.length获取二维数组arr2的2行数 System.out.println("列数"+arr2[0].length); //数组名[任意行,一般用第一行,0],即可确定每一行有多少列 for(int i=0;i<arr2.length;i++) { for(int j=0;j<arr2[0].length;j++) { System.out.print(arr2[i][j]); //不换行,输出 } System.out.println("\n");//换行 } //System.out.println("方法1创建的效果:\n"+arr2); int arr3[][]=new int[][]{{1,2,3},{4,5,6}}; //方法2 for(int i=0;i<arr2.length;i++) { for(int j=0;j<arr2[0].length;j++) { System.out.print(arr2[i][j]); } System.out.println("\n"); } //System.out.println("方法2创建的效果:\n"+arr3); //方法3 int arr4[][]=new int [2][3]; //arr4[0]= {1,2,3};报错,对二维数组进行一维处理时, //必须使用 new方法,一维二维辨别 arr4[0]=new int[] {1,2,3}; //对二维数组第一行进行2初始化 //arr4[1]=new int[] {4,5,6};或者 arr4[1][0]=4; arr4[1][1]=5; arr4[1][2]=6; //分别对第二行每个元素赋值 for(int a[]:arr4) { //foreach语句输出二维数组 for(int b:a) { System.out.print(b); } System.out.println(); } } }
运行结果:
行数2
列数3
123456
123
456
123
456
package 第六章_数组;
public class T4遍历数组 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
char ch[][]=new char[4][];
//创建一个4行的数组,列未知,合法
ch[0]=new char[] {'春','眠','不','觉','晓'};
//对行进行初始化
ch[1]=new char[] {'处','处','闻','啼','鸟'};
ch[2]=new char[] {'夜','来','风','雨','声'};
ch[3]=new char[] {'花','落','知','多','少'};
System.out.println("---双for语句遍历----");
for(int i=0;i<ch.length;i++) {
for(int j=0;j<ch[0].length;j++) {
System.out.print(ch[i][j]);
}//不适用println(自动换行),而是在外循环输出一行后,进行换行
System.out.println();
//外循环输出一行后,进行换行
}
System.out.println("----foreach语句遍历----");
System.out.println("foreach语句遍历二维数组的原理,将二维转换为一维,然后,依次输出");
for(char a[]:ch) {
//控行,利用foreach语句遍历所有元素特点,
//将ch数组的行(共4行)全部作为元素,赋值给一个数组a
for(char b:a) {
//将数组a(这是一个一维数组)的元素,也就是每一个索引位置的值输出
System.out.print(b);//不换行,输出
}
System.out.println();//输出玩一行后,进行换行
}
}
}
运行结果:
—双for语句遍历----
春眠不觉晓
处处闻啼鸟
夜来风雨声
花落知多少
----foreach语句遍历----
foreach语句遍历二维数组的原理,将二维转换为一维,然后,依次输出
春眠不觉晓
处处闻啼鸟
夜来风雨声
花落知多少
- 填充与替换
填充时,会覆盖原始数据,数组N个元素,最多填写N个,超过N就会数据越界
重点:
涉及有关索引的范围操作,如(a,b)均是包括起点a
,但是不包括终点b
,即a
到(b-1)
索引有效
package 第六章_数组;
import java.util.Arrays;
public class T5数组填充替换 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
int arr[]=new int[5];//只对索引0进行了赋值,其它未赋值的将默认赋值为int的默认值0
arr[0]=1;
System.out.println("使用填充前效果:");
for(int i=0;i<arr.length;i++) {
System.out.println("索引"+i+"\t"+arr[i]);
}
System.out.println("使用填充后,进行覆盖效果:");
Arrays.fill(arr, 10);//对数组arr索引进行填充,填充值10
for(int i=0;i<arr.length;i++) {
System.out.println("索引"+i+"\t"+arr[i]);
}
//即便arr[0]=1,但被填充进行了覆盖
System.out.println("--指定位置替换--");
int arr1[]=new int[] {1,2,3,4,5};
System.out.println("替换前效果:");
for(int i=0;i<arr.length;i++) {
System.out.println("索引"+i+"\t"+arr1[i]);
}
System.out.println("替换后效果:");
Arrays.fill(arr1,1,3,9);//替换范围索引1---(3-1) 3的位置最多填5
for(int i=0;i<arr.length;i++) {
System.out.println("索引"+i+"\t"+arr1[i]);//空8格
}
}
}
运行结果:
使用填充前效果:
索引0 1
索引1 0
索引2 0
索引3 0
索引4 0
使用填充后,进行覆盖效果:
索引0 10
索引1 10
索引2 10
索引3 10
索引4 10
–指定位置替换–
替换前效果:
索引0 1
索引1 2
索引2 3
索引3 4
索引4 5
替换后效果:
索引0 1
索引1 9
索引2 9
索引3 4
索引4 5
号码掩盖
package 第六章_数组;
import java.util.Arrays;
public class T6数组填充替换 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
int arr[]=new int[] {1,8,7,9,0,8,8,3,2,3,7};
//快递单号码掩盖
Arrays.fill(arr,3,7,0);
//直接将其替换为*报错,先替换为0,在用if判断
for(int i=0;i<arr.length;i++) {
if(arr[i]==0) {
//判断是否=0,是换为*,存在bug其它位置有0,怎么办?
//if(arr[i]==0&&i<7)
System.out.print("*");
}else {
System.out.print(arr[i]);
}
}
}
}
运行结果:
187****3237
6.3.数组排序
-
可以对int double等进行迅速排序,但是只能进行
升序
-
Java中数组排序根据算法的是
字典编排顺序
,所以,数字在字母前面,大写字母在小写字母前面
package 第六章_数组;
import java.util.Arrays;
public class T7数组排序 {
//只能进行升序排序
public static void main(String[] args) {
// TODO 自动生成的方法存根
int a[]= {2,1,6,0};
double b[]= {1.2,0.3,5,9,3.5};
Arrays.sort(a);
for(int c:a) {//对上一句的a进行操作,所以不需要使用for(int c[]:a)
System.out.print(c+"\t");//不换行,每个数空8格
}
System.out.println();
for(double d:b) {
System.out.print(d+"\t");
}
}
}
运行结果:
0 1 2 6
1.2 0.3 5.0 9.0 3.5
6.4.复制数组
-
背景:牵一发动全身,显然不是我们要的结果?
-
使用Arrays.copyOf
-
指定长度小于原数组,则复制前面的,后面的舍去,指定长度大于原长度,则会自动添加数组类型的默认值(int的默认值为0,char型为null)
package 第六章_数组;
import java.util.Arrays;
public class T8赋值数组 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
int arr[]= {1,2,3,4};
//Arrays.copyOf(arr, 0);报错
System.out.println("指定数组长度小于原数组长度:");
int b[]=Arrays.copyOf(arr, 2);
for(int tem:b) {
System.out.print(tem);//复制前两个
}
System.out.println();
System.out.println("指定数组长度等于原数组长度:");
int c[]=Arrays.copyOf(arr,arr.length);//自动获取数组长度
for(int tem:c) {
System.out.print(tem);
}
System.out.println();
System.out.println("指定数组长度大于原数组长度:");
int d[]=Arrays.copyOf(arr, 8);
for(int tem:d) {
System.out.print(tem);//补充默认值
}
}
}
运行结果:
指定数组长度小于原数组长度:
12
指定数组长度等于原数组长度:
1234
指定数组长度大于原数组长度:
12340000
6.5.数组查询
- 背景
- Arrays类的binarySearch()方法
- 使用二分搜索法来搜索指定数组获得指定对象
- 返回要搜索元素的索引值或者没有这个元素就返回-1 (- 插入点(应该在哪里插入)
- 一般使用Arrays.sort()先对数组进行排序,以保证准确查找
- 指定范围是 1------(n-1)
-
格式:
- binarySearch(Object[ ] a,Object key)
- a:要搜索的数组
- key:要搜索这个数组中的哪一个
-
例如:
-
int arr[ ]=new int[ ]{4,25,10};
Arrays.sort(arr);//将数组arr元素从小到大排序
4 10 25
int index=Arrays.binarySearch(arr,0,1,8);在搜索范围索引0—1中,显然没有8,故返回值:-2(0—1中没有,应该在索引2也就是25的位置上插入8)
查询没有,返回“-(终点+1)”
-
package 第六章_数组;
import java.util.Arrays;
public class T11数组查询 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
int arr[]= {19,2,5,2};//直接实例化数组
Arrays.sort(arr);//将数组元素小到大排序
int index1=Arrays.binarySearch(arr, 5);
//找出数组arr中元素5的索引
int index2=Arrays.binarySearch(arr, 10);
System.out.println("元素5的位置:"+"\t"+index1);//8格为准
System.out.println("元素10的位置:"+"\t"+index2);//8格为准
//数组中没有10,返回值-(插入点索引4)
int arr1[]= {4,1,5,8,10};
// 1 4 5 8 10
Arrays.sort(arr1);
int index3=Arrays.binarySearch(arr1, 0, 2, 5);
//指定范围是包括起点不包括终点,故不包括索引2,所以返回索引应该为-3 -(重点+1)
System.out.println("元素5的位置:"+"\t"+index3);
}
}
元素5的位置: 2
元素10的位置: -4
元素5的位置: -3
6.6.冒泡排序重点掌握
- 核心:比较相邻的两个数,把
大的数
往后面传,或者大的数忘前传
- 规律:
- n个数比较,循环n-1次
- n-(循环顺序)=本次循环应比较几次
- 几个数比较等于数组长度
package 第六章_数组;
public class T9冒泡排序 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
int a[]= {5,2,4,8,0};
for(int i=1;i<a.length;i++){
//第几轮比较,自动获取数组长度
for(int j=0;j<a.length-i;j++) {
//本轮要比较的次数,数组长度就是有几个数在比较,减去第几轮=本轮比较次数
if(a[j]>a[j+1]) {
int tem=a[j];
//先装着前面哪个更大的数
a[j]=a[j+1];
//将更小的数忘前传
a[j+1]=tem;
//完成本轮比较
}
}
}
System.out.println("冒泡排序结果(小到大):");
for(int b:a) {
System.out.print(b+"\t");
//输出比较后,数组顺序
}
System.out.println( );
for(int i=1;i<a.length;i++) {
for(int j=0;j<a.length-i;j++) {
if(a[j]<a[j+1]) {
int tem=a[j];
//先装着更小的值
a[j]=a[j+1];
//更大的值往前推
a[j+1]=tem;
//更小的值往后推
}
}
}
System.out.println("冒泡排序结果(大到小):");
for(int c:a) {
System.out.print(c+"\t");
}
}
}
冒泡排序结果(小到大):
0 2 4 5 8
冒泡排序结果(大到小):
8 5 4 2 0
6.7.选择排序重点掌握
-
比较速度比冒泡排序快,不局限于两个相邻的数比较,而是一个最大的数与剩余所有的数进行比较,大的怎么样安置,小的怎么安置
-
六个数,循环五轮
package 第六章_数组;
//两个进行交换,一定是用第三个数去先装着被替换的数的值
public class T10选择排序 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
int a[]= {3,7,1,0};
int index;
//定义一个指针,始终指向第一个位置的数
for(int i=1;i<a.length;i++) {//
index=0;
for(int j=1;j<=a.length-i;j++) {
//length-i保证始终代表数组最后一个数,
//注意数组每进行一轮比较,均会长度-1
//index已经代表第一个位置的数,所以j=0开始没有意义
if(a[index]<a[j]) {
//在本次for循环中,a[index],a[j]的值随时在变化,每次都是从a[index(即第一个a[0])]开始,
//以第一轮为例,a[0]分别与a[1]a[2]a[3]比较,shuzu长度=4-1(第一轮)
index=j;
//此时index位置变成了最大的数
}
}
//在数组中,最后一个位置数的索引,一定是[数组名.length-1]
int tem=a[a.length-i];//把本轮比较中,最后一个数传递给第三方
a[a.length-i]=a[index];
a[index]=tem;
//最大的数已经成功推到最后面了,将比较前最后一个位置的数
//给index这个位置(除最后一个位置以外,任意一个位置)
//至此,已经完成本轮比较中最大的数与最后一个位置进行交换位置的事
}//外循环for的大括号,一轮循环的结束点
/*
使用foreach语句将选择排序后的数组输出,不同方法中,可以用重名,作用域:本方法内
*/
System.out.println("选择排序(从小到大):");
for(int tem:a) {
System.out.print(tem+"\t");//不空行
}
System.out.println();
for(int i=1;i<a.length;i++) {
index=0;
for(int j=1;j<=a.length-i;j++) {
if(a[index]>a[j]) {
index=j;
//此时index位置的数变成最小的数
}
}
int tem=a[a.length-i];
a[a.length-i]=a[index];
a[index]=tem;
}
System.out.println("选择排序(从大到小):");
for(int tem:a) {
System.out.print(tem+"\t");
}
}
}
运行结果:
选择排序(从小到大):
0 1 3 7
选择排序(从大到小):
7 3 1 0
6.8.反转排序
重点掌握方法的创建和调用,后面第七章类和对象会详细介绍
-
将数组最后一个元素与第一个元素进行调换,然后倒数第二个与第二个调换,依次类推
-
for循环只需进行数组长度半次,数组长度=7或6,均循环3次
-
package 第六章_数组; public class T12反转排序 { /*------------自定义一个遍历数组的成员方法showArray(int[]array)--------*/ public void showArray(int[]array) { for(int i:array) { //foreach遍历数组 System.out.print("\t"+i); } System.out.println(); //遍历结束后换行 } /*-------自定义一个反转排序的成员方法sort(int[]array)-----------*/ public void sort(int[]array) { System.out.println("反转排序前的内容"); showArray(array); //处于同一个类内部,故可以直接调用 int temp; for(int i=0;i<array.length/2;i++) { temp=array[i]; array[i]=array[array.length-1-i]; //原来-i就行,但是数组最后一个元素是数组.length-1 //array[array.length-1-i]代表的是最后一个索引位置 array[array.length-1-i]=temp; } System.out.println("反转排序后的内容"); showArray(array); } public static void main(String[] args) { // TODO 自动生成的方法存根 int[]array= {1,2,3,4,5,6,7,8,9}; T12反转排序 a=new T12反转排序(); /*若不想创建类的对象a,就直接调用自定义的sort方法 * 在自定义的两个方法开头加上static,将两个成员方法改为 * 静态成员方法*/ a.sort(array); //成员方法与主方法不在同一个内存空间内,调用前类的实例化 } }
反转排序前的内容
1 2 3 4 5 6 7 8 9
反转排序后的内容
9 8 7 6 5 4 3 2 1