引言
现在目前我们的一个变量,最多就保存一个数据,显然不科学。目前需要一个方案来解决这个问题,可以保存多个数据的容器。在几乎所有的编程语言中都提供了数组这么一个概念,数组它是一种基础的数据结构(列表数据结构)。
一. 数组概念
1.1 基本概念
数组它是存放 一组类型相同,个数有限的数据的容器。数组也是变量,由于它的数据结构的特点可以保存多个数据,数组在内存中,往往是块连续有限的空间。
1.2 图形理解
二 . 数组的声明与赋值
数组它是一种引用数据类型,它的存储需要使用到两块内存空间(堆和栈),基本数据类型只需要栈空间
2.1 数组声明语法
声明:
声明并分配空间 int[] a = new int[5];
先声明 再分配空间 int a =[]; a =new int[5]; 局部变量存在栈中
声明并赋值(繁) int [] b; b=new int[]{11,22,33,44,55};
声明并赋值(简) int [] c = {1,2,3,4,5};
2.2 数组内存分配

数组初始化后,会为元素赋予初始值,比如整型数组默认为0 浮点数数组默认为0.0 引用数据类型数组为 null。
三 . 数组的组成
3.1 数组元素寻址
数组由各个元素构成,各个元素依次排列,每个元素都有一个寻址下标,选址下标自动生成,从0开始。首地址结合下标通过偏移就可以寻址到每个元素,这里有一个问题就是,如果偏移的过程中,超过了下标,会造成数组下标越界问题。最大下标为数组长度-1。
3.2 获得数组长度
3.3 数组下标越界
Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 这个异常就是数组下标超出了范围。
下标的范围:0 - 数组长度减一
数组默认值:(没有赋值的情况下)
整数:0
小数:0.0
字符:\u0000
布尔:false
其他:null
public static void main(String[] args) {int[] scores = new int[5];//存数据:赋值scores[0] = 1;scores[1] = 2;scores[2] = 3;scores[3] = 4;scores[4] = 5;//取数据:System.out.println( scores[0] );System.out.println( scores[1] );System.out.println( scores[2] );System.out.println( scores[3] );System.out.println( scores[4] );}
四 . 数组的遍历
数组遍历,指的是将元素依次访问一遍,通常这个过程需要借助循环实现,这里介绍两种常见遍历数组的方式
4.1 通过普通for循环
借助循环的连续的循环变量作为下标。
public static void main(String[] args) {int[] scores = new int[5];//存数据:赋值scores[0] = 1;scores[1] = 2;scores[2] = 3;scores[3] = 4;scores[4] = 5;//取数据:System.out.println( scores[0] );System.out.println( scores[1] );System.out.println( scores[2] );System.out.println( scores[3] );System.out.println( scores[4] );//数组遍历(把每个元素都访问一遍 != 输出 )System.out.println("---遍历方式1--"); //天意:循环计数器可以是连续的,恰好用在这里当下标for( int i =0 ; i< scores.length ; i++ ){System.out.println( scores[i] );}Arrays.sort()Scnnar sc = new Scanner()sc.nextInt();}
4.2 通过增强for循环foreach
此方法是一种语法糖,也就是编写上的形式方便,底层依然采用普通for实现
public static void main(String[] args) {int[] scores = new int[5];//存数据:赋值scores[0] = 1;scores[1] = 2;scores[2] = 3;scores[3] = 4;scores[4] = 5;//取数据:System.out.println( scores[0] );System.out.println( scores[1] );System.out.println( scores[2] );System.out.println( scores[3] );System.out.println( scores[4] );//数组遍历 (增强for循环 语法糖= 编译的时候会过程叫 解语法糖,会采用基础原生的方式实现 )System.out.println("---遍历方式2--");for( int element : scores ){System.out.println(element);}}
五. 数组应用
5.1 基本使用
5.2 数组作为参数
5.3 数组作为返回值
/**数组作为返回值类型*/public class ArrayUesdReturn {//编写一个程序,生成一个数字验证码 (4位)public static int[] createCode(){int[] codeArray = new int[4];Random rd = new Random();for(int i=0;i<4;i++){int n = rd.nextInt(10);codeArray[i]=n;}System.out.println("codeArray的地址"+codeArray);return codeArray;}public static void main(String[] args) {int[] result = createCode(); // ctrlSystem.out.println("result的地址"+result);ArrayUsedArgs.printArray(result);}}
5.4 值传递与地址传递
- 对于基本数据类型,传参为值的拷贝,当然返回的也是值的拷贝。
- 对于引用数据类型, 传参实际是地址传递,当然返回的也是地址。 ```java public class ValueAndRefrence {
public static void main(String[] args) {int age = 10;change(age);System.out.println(age); // 10int[] brr = {10,20};change2(brr);System.out.println(brr[0]+" "+brr[1]);// 100 20}public static void change(int num ){num = 100;}public static void change2(int[] arr){arr[0] = 100;}
}
<a name="WEN3D"></a>#### 5.5 数组的扩容什么是扩容?<br />扩容指的是扩展存储空间容量,为什么要扩容?<br />数组是的容量是声明是就确定了的(定死了)后续不可以被修改,但是我们实际情况又需要更多的容量。这里的"扩容"是一种通过其他手段实现的。因为数组本身长度声明后是不可改变的。```java旧:第一种:int [] c = {1,2,3,4,5};int [] new_c = new int [10];for(int i=0;i<c.length;i++){new_c[i]=c[i];}for (int i = 0; i <new_c.length ; i++){System.out.println(new_c[i]);}第二种:System.arraycopy(原数组,原数组起始,新数组,新数组起始,取到元素的个数);System.arraycopy(c,0,new_c,0,5);第三种:java.util.Arrays.copyOf(原数组,新长度);int[] new_c = Arrays.copyOf(c,10);c=new_c;//第一种扩容System.out.println("第一种扩容");int [] c = {1,2,3,4,5};int [] new_c = new int [10];for(int i=0;i<c.length;i++){new_c[i]=c[i];}for (int i = 0; i <new_c.length ; i++){System.out.println(new_c[i]);}//第二种扩容System.out.println("第二种扩容");int[] new_c2=new int[5];System.arraycopy(c,1,new_c2,0,3);for (int i = 0; i <new_c2.length ; i++){System.out.println(new_c2[i]);}//第三种扩容System.out.println("第三种扩容");int[] new_c3 = Arrays.copyOf(c,10);for (int i = 0; i <new_c3.length ; i++){System.out.println(new_c3[i]);}
5.6 数组元素删除
//封装一个删除方法(可能并不完美哈)public static void delete( String[] data , int index ){System.arraycopy( data, index+1,data,index,data.length-1-index );int l = data.length-1;for(int i=data.length-1;i>0;i--){if( data[l]==null ){}else{data[l]= null;break;}}}
六 . 数组排序与查找
数组排序指的是采用某种算法来将元素按一定次序排列整齐,数组的查找,根据指的元素判断其在数组中的位置
6.1 冒泡排序

取相邻的两个元素比较如果前者大于后则交换,一趟的结果为找出了这趟的最大值,且交换到最最后 ,一致重复趟数直到完成。
相邻两个值比较大小,互换位置
N个数字来排队
两两相比小考前
外层循环N-1
内层循环N-1-i
int temp;for (int i = 0; i <a.length-1 ; i++){//0 1 2 3for (int j = 0; j <a.length-i-1 ; j++){//0 0 1 2 3 4 1 0 1 2 3 2 0 1 2if(a[j]>a[j+1]){temp=a[j];a[j]=a[j+1];a[j+1] = temp;}}}for (int e:a){System.out.println(e);}
6.2 选择排序
固定一个值与其他值比较大小,互换位置
int[] a = {1,3,3,7,5,8,9};for (int i = 0; i <a.length-1 ; i++){int min =i;for (int j = i+1; j <a.length ; j++){if(a[j]<a[i]){min= j;}if(min!=i){int tmp = a[i];a[i] = a[min];a[min] = tmp;}}}for (int e:a){System.out.print(e);}
6.3 插入排序

public static void insert( int[] data){//根据元素个数确定趟数 为什么是1 开始,假设第一个是排好for( int i=1; i< data.length;i++ ){//从未排序区取一个取一个元素data[i+1] 和 已经排序区 比较寻找和位置for( int j=i ; j>0;j-- ){// 1 ,2 3 4 8 3|//如果我们选择的这个数 小于当前元素则交换if( data[j] < data[j-1] ){int t = data[j];data[j]= data[j-1];data[j-1]=t;}}}}
6.4 使用JDK排序
jdk排序:Java.util.Arrays.sort() 默认排序升序
int[] a = {1,6,3,7,5,8,9};Arrays.sort(a);for (int e:a) {System.out.print(e);}
6.5 快速排序原理

- 快速排序,特点就是块, 一般的情况 O(n*lgN ) 最坏情况是n^2
- 它是一种分治的思想。分区( 把数据 分为两个子区, 小于基准数的排列到 左边 大于基准数的排列在右边。 )
- 重复重复上述动作分区( 引入递归 )
- 确定一个基准数。(左边第一个数)
- 从左往右扫,如果小于基准数则继续前行,直到找到第一个大于基准数的值。则保存这个数到右边。
- 从右向左扫,如果大于基准数着继续前行,直到找到第一个小于基准数的值,着包装这个数到左边。
- 重复上诉过程,即可把数据分为两区。

public static void main(String[] args) {int[] data = {38,22,44,23,14,32,28,66,25,88,77,44};quickSort(data, 0, data.length - 1);System.out.println(Arrays.toString(data));}public static void quickSort( int data[] , int left, int right ){if( left<right ){int index = division(data,left,right);quickSort(data,left,index-1);quickSort(data,index+1,right);}}public static int division(int[] data , int left, int right){int pivot = data[left];while (left < right){while ( left < right && data[right] >= pivot )--right;data[left] = data[right];while (left<right && data[left] <= pivot )++left;data[right]=data[left];}data[left]=pivot;return left;}
从数组中找到目标数据,如果寻找,又涉及到相关的算法,典型查找方法,比如线性 查找,或者折半查找。
6.6 线性查找
就是从头到尾查找,如果元素非常多,效率就不高。
package find;import java.util.Arrays;//查找public class FindDemo {public static void main(String[] args) {String[] team = { "诸葛亮","刘备","关羽","大乔","小乔","曹操" };int index = lineFind(team,"吕布");System.out.println(index);//原数组int[] data = {1,3,46,367,312,11,567,44,22,56};//排序Arrays.sort(data);System.out.println(Arrays.toString(data));int index2 = binarySerach(data, 56);//int index2 = Arrays.binarySearch(data, 56);System.out.println(index2);}// 线性查找:更通用,可适用于各种数据类型public static int lineFind(String[] data, String key){for(int i=0; i<data.length; i++){if( data[i].equals(key) ){return i;}}return -1;}}
6.7 折半查找
就是 通过已经排好序的数组,先判断中间值,如果相等则返回,否则不断缩小查找范围
package find;import java.util.Arrays;//查找public class FindDemo {public static void main(String[] args) {//原数组int[] data = {1,3,46,367,312,11,567,44,22,56};//排序Arrays.sort(data);System.out.println(Arrays.toString(data));int index2 = binarySerach(data, 56);//int index2 = Arrays.binarySearch(data, 56);System.out.println(index2);}// 二分查找:针对的是数字查找,且要求数字必须先排序。public static int binarySerach( int[] data , int key ){int left = 0; //左起点int right = data.length-1;//右终点//只要 左起点下标未超过右终点 继续,否则说明 移动交叉了不存在查找的数据 停止查找。while( left<=right ){//计算中间值下标int min = (left+right)/2;// 判断与中间值的大小if( key == data[min]){ // 查到了return min;}else if( key < data[min] ){ // 在左半轴查找right = min-1;}else{ // 在右半轴查找left = min+1;}}//没有找到return -1;}}
七 . 二维数组(了解)
7.1 概念
二维数组从空间上看是有行列组成的结构,但是实际在计算机中,二维数组本质上还是一个一维数组,只是这个一维数组的每个元素,都是一个数组。
7.2 内存理解

数组的每个元素保存的右是 另一个数组的地址。
7.3 创建和声明二维数组
int[][] num = new int[3][5];num[0][1] = 20;num[0][2] = 30;num[0][3] = 40;num[1][2] = 20;num[2][4] = 10;for (int i = 0; i <num.length ; i++) {for (int j = 0; j < num[i].length; j++) {System.out.print(num[i][j]+"\t");}System.out.println();}
7.4 二维数组遍历
public static void main(String[] args) {int[][] data = new int[3][3];//元素的访问:赋值data[0][0] = 1;data[0][1] = 2;data[0][2] = 3;data[1][0] = 4;data[1][1] = 5;data[1][2] = 6;data[2][0] = 7;data[2][1] = 8;data[2][2] = 9;// 普通forfor(int i=0;i<data.length;i++){for(int j=0;j< data[i].length;j++ ){System.out.print(data[i][j]+"\t");}System.out.println();}// 增强forfor( int[] arr : data ){for( int e :arr ){System.out.print(e+"\t");}System.out.println();}}
课后习题:
打印杨辉三角
static void yanghui(int a){int[][] arr = new int[a][a];for (int i = 0; i <a ; i++) {arr[i][0]=1;arr[i][i]=1;}for (int i = 2; i <a ; i++) {for (int j = 1; j <i ; j++) {arr[i][j]=arr[i-1][j-1]+arr[i-1][j];}}for (int i = 0; i <arr.length ; i++) {for (int j = 0; j <arr.length-i-1; j++) {System.out.print(" ");}for (int j = 0; j <= i; j++) {System.out.print(arr[i][j]+" ");}System.out.println();}}
public class Array2 {public static void main(String[] args){int [] b; b=new int[]{11,22,33,44,55};avg(b);xiabiao(b);MaxAndMin(b);Reserve();weizhi();Day();sum_OuShu();}/** 计算传入数组平均值* */static void avg(int[] a){double sum=0;double avg=0;for (int i = 0; i < a.length; i++){sum+=a[i];}avg=sum/a.length;System.out.println("b数组的平均值为:"+avg);}/** 计算传入数的下标* */static void xiabiao(int[] b){Scanner sc =new Scanner(System.in);System.out.print("请输入一个数:");int num =sc.nextInt();for (int i = 0; i < b.length; i++){if (num==b[i]) System.out.println(num+"的下标为:"+i);}}/** 找到最大值和最小值* */static void MaxAndMin(int[] b){int max = b[0];int min = b[0];for (int i = 0; i <b.length ; i++){if(b[i]>max) max=b[i];if(b[i]<min) min=b[i];}System.out.println("MAX is "+max);System.out.println("MIN is "+min);}/** 将数组元素颠倒* */static void Reserve(){int[] b; b=new int[]{11,22,33,44,55};int[] c =new int[b.length];for (int i = 0; i <b.length ; i++) {c[b.length-i-1]=b[i];}System.out.println("原数组");for (int i = 0; i <b.length ; i++) {System.out.print(b[i]+"\t");}System.out.print("\n反转");System.out.println();for (int i = 0; i <c.length ; i++) {System.out.print(c[i]+"\t");}System.out.println();}/** 输出积分最少的数 和 位置* */static void weizhi(){int[] a = {18,25,7,36,13,2,89,63};int min = a[0];for (int i = 0; i <a.length ; i++){if(a[i]<min) min=a[i];}for (int i = 0; i < a.length; i++){if (min==a[i]) System.out.println("最少的积分为:"+min+"所在的下标为:"+i+1);}}/** 输一个日期,输出这个日期是这年的第几天* */static void Day() {Scanner sc = new Scanner(System.in);System.out.print("请输入年份:");int year =sc.nextInt();System.out.print("请输入月份:");int month = sc.nextInt();System.out.print("请输入天数:");int day = sc.nextInt();if((year%4==0&&year%100!=0)||year%400==0){int sum=0;int[] arr1 = {31,29,31,30,31,30,31,31,30,31,30,31};for (int i = 0; i < month-1; i++) {sum+=arr1[i];}sum=sum+day;System.out.println(year+"年"+month+"月"+day+"日"+"是一年中的+"+sum+"天");}else{int sum=0;int[] arr2 = {31,28,31,30,31,30,31,31,30,31,30,31};for (int i = 0; i < month-1; i++) {sum+=arr2[i];}sum=sum+day;System.out.println(year+"年"+month+"月"+day+"日"+"是一年中的"+sum+"天");}}/** 求出下标为偶数和* */static void sum_OuShu(){Scanner sc = new Scanner(System.in);int[] arr = new int[10];for (int i = 0; i <10 ; i++) {System.out.print("请输入第"+(i+1)+"个数字:");arr[i] = sc.nextInt();}int sum=0;for (int i = 0; i <arr.length ; i+=2) {sum+=arr[i];}System.out.println("下标为偶数的元素之和为:"+sum);}}
