数组一、概念1、什么是数组数组Array是有序的元素序列。若将有限个类型相同的变量的集合命名那么这个名称为数组名。组成数组的各个变量称为数组的分量也称为数组的元素有时也称为下标变量。用于区分数组的各个元素的数字编号称为下标。2、特点数组是相同数据类型的元素的集合。数组中的各元素的存储是有先后顺序的它们在内存中按照这个先后顺序连续存放在一起。数组元素用整个数组的名字和它自己在数组中的顺序位置来表示。例如a[0]表示名字为a的数组中的第一个元素a[1]代表数组a的第二个元素以此类推。3、存储形式堆内存用来存放由new运算符创建的对象和数组在堆中分配的内存由java虚拟机的自动垃圾回收器来管理。在堆中创建了一个数组或对象后同时还在栈内存中定义一个特殊的变量。让栈内存中的这个变量的取值等于数组或者对象在堆内存中的首地址栈中的这个变量就成了数组或对象的引用变量引用变量实际上保存的是数组或对象在堆内存中的地址也称为对象的句柄以后就可以在程序中使用栈的引用变量来访问堆中的数组或对象。二、数组的使用1、数组的创建语法/*格式1 元素类型[] 数组名 new 元素类型[元素个数或数组长度]; 示例 */int[]arrnewint[5];/* 格式2 元素类型[] 数组名 new 元素类型[]{元素元素……}; */int[]arrnewint[]{3,5,1,7};int[]arr{3,5,1,7};注数组的元素是通过索引访问的。数组索引从 0 开始所以索引值从 0 到 arr.length-1。且给数组分配空间时必须指定数组能够存储的元素个数来确定数组大小。创建数组之后不能修改数组的大小。可以使用length 属性获取数组的大小。例public static void creatArray(){ // 数组大小 int size 10; // 定义数组 double[] myList new double[size]; for (int i 0;i 10;i){ myList[i] i; } // 计算所有元素的总和 double total 0; for (int i 0; i size; i) { System.out.print(myList[i] ); total myList[i]; } System.out.println(); System.out.println(总和为 total); }图解2、数组的遍历代码演示//方式一for循环publicstaticvoidlistFor(){int[]arrs{1,3,4,5,6,6,7};for(inti0;iarrs.length;i){System.out.print(arrs[i] );}}//方式二for-eachpublicstaticvoidlistFor(){int[]arrs{1,3,4,5,6,6,7};for(intarr:arrs){System.out.print(arr );}}结果3、数组常见异常NullPointerException 空指针异常原因 引用类型变量没有指向任何对象而访问了对象的属性或者是调用了对象的方法。ArrayIndexOutOfBoundsException 索引值越界。原因访问了不存在的索引值。4、数组内存分析三、Arrays常用方法Arrays具有以下功能给数组赋值通过 fill 方法。对数组排序通过 sort 方法,按升序。比较数组通过 equals 方法比较数组中元素值是否相等。查找数组元素通过 binarySearch 方法能对排序好的数组进行二分查找法操作。1、fill(int[] a, int val)作用 将指定的 int 值分配给指定 int 型数组指定范围中的每个元素。同样的方法适用于所有的其他基本数据类型ByteshortInt等。使用publicstaticvoidfill(){int[]arrs{1,3,4,5,6,6,7};Arrays.fill(arrs,2);System.out.println(Arrays.toString(arrs));}结果Jdk分析//使用val对a数组进行数据填充publicstaticvoidfill(long[]a,longval){fill(a,0,a.length,val);}//使用val对a数组从fromIndex(包含至toIndex不包含位置进行数据填充publicstaticvoidfill(long[]a,intfromIndex,inttoIndex,longval){rangeCheck(a.length,fromIndex,toIndex);for(intifromIndex;itoIndex;i)a[i]val;}2、sort(Object[] a)作用对指定对象数组根据其元素的自然顺序进行升序排列。同样的方法适用于所有的其他基本数据类型ByteshortInt等。使用publicstaticvoidsort(){int[]arrs{1,5,4,6,3,6,2};System.out.println(Arrays.toString(arrs));Arrays.sort(arrs);System.out.println(Arrays.toString(arrs));}结果Jdk源码//对数组a进行排序publicstaticvoidsort(long[]a){sort1(a,0,a.length);}//对数组a中的从fromIndex(包含至toIndex(不包含)的值进行排序publicstaticvoidsort(long[]a,intfromIndex,inttoIndex){rangeCheck(a.length,fromIndex,toIndex);sort1(a,fromIndex,toIndex-fromIndex);}/** 对基本类型数组的排序有以上两种方法这里只摘出了long类型的。sort1方法篇幅原因没有摘出来在sort1方法中使用的是经过调优的快速排序算法tuned quicksort。 **/..............................//对对象类型进行排序publicstaticvoidsort(Object[]a){Object[]aux(Object[])a.clone();mergeSort(aux,a,0,a.length,0);}//对对象a中的从fromIndex(包含至toIndex(不包含)的值进行排序publicstaticvoidsort(Object[]a,intfromIndex,inttoIndex){rangeCheck(a.length,fromIndex,toIndex);Object[]auxcopyOfRange(a,fromIndex,toIndex);mergeSort(aux,a,fromIndex,toIndex,-fromIndex);}/** 对对象类型数组的排序有以上两种方法在mergeSort方法中使用的是经过修改的归并排序算法modified mergesort。 **/3、equals(long[] a, long[] a2)作用 如果两个指定的 long 型数组彼此相等则返回 true。如果两个数组包含相同数量的元素并且两个数组中的所有相应元素对都是相等的则认为这两个数组是相等的。换句话说如果两个数组以相同顺序包含相同的元素则两个数组是相等的。同样的方法适用于所有的其他基本数据类型ByteshortInt等。使用publicstaticvoidequal(){int[]arrs1{1,5,4,6,3,6,2};int[]arrs2{1,5,4,6,3,6,2};int[]arrs3{1,2,3,4,5,6,2};System.out.println(Arrays.equals(arrs1,arrs2));System.out.println(Arrays.equals(arrs1,arrs3));}结果Jdk源码//比较基本类型数组是否相等publicstaticbooleanequals(long[]a,long[]a2){if(aa2)returntrue;if(anull||a2null)returnfalse;intlengtha.length;if(a2.length!length)returnfalse;for(inti0;ilength;i)if(a[i]!a2[i])returnfalse;/** 对于double类型使用的是 if (Double.doubleToLongBits(a[i])!Double.doubleToLongBits(a2[i])) return false; 对于float类型使用的是 if (Float.floatToIntBits(a[i])!Float.floatToIntBits(a2[i])) return false; 这样做是为了精确比较。 **/returntrue;}...............//比较Object类型数组是否相等publicstaticbooleanequals(Object[]a,Object[]a2){if(aa2)returntrue;if(anull||a2null)returnfalse;intlengtha.length;if(a2.length!length)returnfalse;for(inti0;ilength;i){Objecto1a[i];Objecto2a2[i];if(!(o1null?o2null:o1.equals(o2)))returnfalse;}returntrue;}...............//深度比较两个数组是否相等publicstaticbooleandeepEquals(Object[]a1,Object[]a2){if(a1a2)returntrue;if(a1null||a2null)returnfalse;intlengtha1.length;if(a2.length!length)returnfalse;for(inti0;ilength;i){Objecte1a1[i];Objecte2a2[i];if(e1e2)continue;if(e1null)returnfalse;// Figure out whether the two elements are equalbooleaneq;if(e1instanceofObject[]e2instanceofObject[])eqdeepEquals((Object[])e1,(Object[])e2);elseif(e1instanceofbyte[]e2instanceofbyte[])eqequals((byte[])e1,(byte[])e2);elseif(e1instanceofshort[]e2instanceofshort[])eqequals((short[])e1,(short[])e2);elseif(e1instanceofint[]e2instanceofint[])eqequals((int[])e1,(int[])e2);elseif(e1instanceoflong[]e2instanceoflong[])eqequals((long[])e1,(long[])e2);elseif(e1instanceofchar[]e2instanceofchar[])eqequals((char[])e1,(char[])e2);elseif(e1instanceoffloat[]e2instanceoffloat[])eqequals((float[])e1,(float[])e2);elseif(e1instanceofdouble[]e2instanceofdouble[])eqequals((double[])e1,(double[])e2);elseif(e1instanceofboolean[]e2instanceofboolean[])eqequals((boolean[])e1,(boolean[])e2);elseeqe1.equals(e2);if(!eq)returnfalse;}returntrue;}4、binarySearch(Object[] a, Object key)作用 用二分查找算法在给定数组中搜索给定值的对象(Byte,Int,double等)。数组在调用前必须排序好的。如果查找值包含在数组中则返回搜索键的索引否则返回 (-(插入点) - 1)。使用publicstaticvoidbinarySearch(){int[]arrs1{1,5,4,6,3,6,2};Arrays.sort(arrs1);System.out.println(Arrays.binarySearch(arrs1,4));}结果Jdk源码/** 对数组中元素的查找有以上两种方法在binarySearch0方法中使用的是二分查找法。并且对基本类型和对象类型的数组查找是同样的操作。 **/publicstaticintbinarySearch(long[]a,longkey){returnbinarySearch0(a,0,a.length,key);}publicstaticintbinarySearch(long[]a,intfromIndex,inttoIndex,longkey){rangeCheck(a.length,fromIndex,toIndex);returnbinarySearch0(a,fromIndex,toIndex,key);}注参考博客oguroRainnnbow