数组
数组的概念
数组是一组具有相同类型的数据的有序集合。
数组描述的是相同类型的若干个数据,按照一定的先后次序(index)排列组合而成。其中,每一个数据称作一个数组元素(item),每个数组元素可以通过一个下标(index)来访问它们。
数组特性:
- 数组的长度是确定的。通过length属性方法。其长度一旦确定,就不能更改。=> 数组不能自动拓容。
- 数组元素必须是相同类型。数组本身可以是任意类型,但其元素都必须是同一类型。也就是说,整形数组只能存整形数据。
- 数组元素有序。数组的元素通过下标(index)访问,下标从0开始。
数组是引用数据类型。
内存分区
栈区(stack):基本数据类型所在内存区,栈区没有默认值一说,栈区的变量必须先声明后赋值再使用。栈区的变量使用完后,不需要释放空间,系统会自动回收。栈区空间相对较小。
堆区(heap):所有引用数据类型所在的内存区。堆区有默认值一说。堆区必须要new申请空间才能使用。堆区的变量使用完成后,gc回收内存空间。堆区空间相对较大。
声明数组
声明数组4步:
[1] 声明数组
[2] 在堆区分配空间
[3] 赋值
[4] 使用
public class Test{ public static void main(String[] args){ // [1]声明数组 => 在栈区申请变量空间 int[] a; int b; b = 100; // [2]申请内存空间 a = new int[5]; System.out.println(a[0]); System.out.println(a[1]); System.out.println(a[2]); System.out.println(a[3]); System.out.println(a[4]); // [3]赋值 a[0] = 8; // [4]使用a[0]; System.out.println(a[0]); } } |
总结
基本数据类型和引用数据类型的区别是基本数据类型直接存放值,引用数据类型存放的是堆区内存地址。
[1]length表示数组的长度
[2]数组的最大下标永远比length少1
public class Test{ public static void main(String[] args){ // int a = 10; int[] a = new int[5]; System.out.println(a); // [1]length:数组的长度(空间) System.out.println(a.length); // [2]数组越界 System.out.println(a[5]); } } |
[3]数组的遍历
// [3]数组遍历 a[0] = 1; a[1] = 2; a[2] = 3; a[3] = 4; a[4] = 5; for(int i=0;i<a.length;i++){ System.out.println("a[" +i+"]=" + a[i]); } |
其他声明方式:
public class Test{ public static void main(String[] args){ // [1]申请好内存空间 int[] arr = new int[5]; /* int[] arr; arr = new int[5]; */ arr[0] = 1; // [2] int[] arr2 = new int[]{1,2,3,4,5}; /* int[] arr2; arr2 = new int[]{1,2,3,4,5}; */ System.out.println(arr2); for(int i=0;i<arr2.length;i++){ System.out.println(arr2[i]); } // [3] 字面量赋值 //int[] arr3 = {1,2,3,4,5}; // 错误的写法 /* int[] arr3; arr3 = {1,2,3,4,5}; */ for(int i=0;i<arr3.length;i++){ System.out.println(arr3[i]); } } } |
数组的应用
数组的插入操作
向数组中添加一个元素,保持数组依然有序。
字符串可以比较大小,比较规则:
取两个字符串中的第1个字符按照ascii比较,如果比较出结果,停止比较;如果第一个字符相同,取第二个按照ascii比较,依次类推。和字符串的长度无关。
str1.compareTo(str2) 用于字符串的比较,其返回值反映了字符串大小。
<0 str1<str2 升序
=0 str1=str2 相等
>0 str1>str2 降序
数组的删除操作
public class Test{ public static void main(String[] args){ String[] arr = {"island","ocean","pretty","ready","sun"}; String str = "pretty"; int loc = -1; for(int i=0;i<arr.length;i++){ /* if(arr[i].compareTo(str) == 0){ loc = i; break; }*/ if(arr[i].equals(str)){ loc = i; break; } } if(loc < 0){ System.out.println("no element in array"); }else{ for(int j=loc;j<arr.length-1;j++){ arr[j] = arr[j+1]; } // null 表示空引用/空指向 arr[arr.length - 1] = null; } for(String item:arr){ System.out.println(item); } } } |
注意:
删除一个元素后,数组的最后一个位置空出来了,一定要赋值一个默认值。如果数组存储的是引用数据类型,默认值是null。null表示空引用。
数组的排序
数组排序算法很多,大概8大排序算法。
常见的内部排序算法有:冒泡排序(A)、插入排序、快速排序、选择排序、归并排序、希尔排序、堆排序、基数排序等。
冒泡排序
思想:假定有5个元素,
让5个元素两两相互比较,如果前一个比后一个大,互换位置,否则不换。5个数两两比较需要比较4次。我们把这个过程称为一趟。一趟下来,产生一个大数。
让剩余的4个数两两比较,如果前一个比后一个大,互换位置,否则不换。4个数两两比较需要比较3次。我们把这个过程称为第二趟。第二趟下来,又产生一个大数。
依次类推。
public class Test{ public static void main(String[] args){ int[] arr = {5,3,4,2,1}; // 先控制趟数 int tmp = 0; for(int i=0;i<arr.length-1;i++){ for(int j=0;j<arr.length-1-i;j++){ if(arr[j] > arr[j+1]){ tmp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = tmp; } } } for(int item:arr){ System.out.print(item+"\t"); } } } |
封装冒泡算法
public class Test{ public static int[] bubble(int[] arr){ int tmp = 0; for(int i=0;i<arr.length-1;i++){ // 控制趟数 for(int j=0;j<arr.length-1-i;j++){ // 控制两两比较的次数 if(arr[j] > arr[j+1]){ tmp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = tmp; } } } return arr; } public static void main(String[] args){ int[] arr = {5,3,4,2,1}; int[] sortedArr = bubble(arr); for(int item:sortedArr){ System.out.print(item+"\t"); } } } |
命令行参数
在运行java程序时,可以向程序传递0-多个参数,这个产生叫做命令行参数。命令行参数以空格分割多个参数。如果传递的参数本身包含空格,用“”引起来。
数组常用方法
import java.util.Arrays; public class Test{ public static void main(String[] args){ // 【1】toString():把数组转化成对于的字符串 int[] arr = {1,2,3,4,5}; System.out.println(Arrays.toString(arr)); // 【2】sort():把数组进行升序排序 int[] arr2 = {3,5,4,2,1,6}; Arrays.sort(arr2); System.out.println(Arrays.toString(arr2)); // 【3】binarySearch(arr,key):在有序的数组中查找key值是否存在,如果存在返回其索引 int index = Arrays.binarySearch(arr2,4); System.out.println("index = " + index); } } |
二分法查找
前提:有序的数组.
思想:
(1)首先,从数组的中间元素开始搜索,如果该元素正好是目标元素,则搜索过程结束,否则执行下一步。
(2)如果目标元素大于/小于中间元素,则在数组大于/小于中间元素的那一半区域查找,然后重复步骤(1)的操作。
(3)如果某一步数组为空,则表示找不到目标元素。
private static int binarySearch0(int[] a, int fromIndex, int toIndex, int key) { int low = fromIndex; int high = toIndex - 1; while (low <= high) { int mid = (low + high) >>> 1; int midVal = a[mid]; if (midVal < key) low = mid + 1; else if (midVal > key) high = mid - 1; else return mid; // key found } return -(low + 1); // key not found. } |
数组的复制
数组的复制: int[] arr6 = {7,2,3,4,5,6}; int[] newArr = Arrays.copyOf(arr6,10); System.out.println(Arrays.toString(newArr));
//【6】arraycopy(Object src, int srcPos, Object dest, int destPos, int length) int[] arr7 = {1,2,3,4,5}; int[] newArr2 = {1,1,1,0,0,0,0}; System.arraycopy(arr7,1,newArr2,3,4); System.out.println(Arrays.toString(newArr2)); |
src - 源数组。
srcPos - 源数组中的起始位置。
dest - 目标数组。
destPos - 目标数据中的起始位置。
length - 要复制的数组元素的数量。
二维数组
一个一维数组A中的每个元素又是一个一维数组,这个数组A称为二维数组。
二维数组的内存原理:
声明二维数组
int[][] arr = new int[3][]
表示声明了一个二维数组arr,arr可以存3个一维数组。
public class Test{
public static void main(String[] args){
// int[] arr = new int[4];
// [1]声明一个二维数组
int[][] arr;
// [2]申请空间
arr = new int[3][];
// 二维数组的长度
System.out.println(arr.length);
for(int i=0;i<arr.length;i++){
System.out.println(arr[i]);
}
// System.out.println(arr);
}
}
二维数组的赋值:
public class Test{ public static void main(String[] args){ // int[] arr = new int[4]; // [1]声明一个二维数组 int[][] arr; // [2]申请空间 arr = new int[3][]; // [3]给二维数组赋值 int[] arr1 = new int[]{1,2,3,4,5,6}; arr[0] = arr1; int[] arr2 = {1,2,3,4}; arr[1] = arr2; int[] arr3 = new int[4]; arr3[0] = 1; arr3[1] = 2; arr3[2] = 3; arr3[3] = 4; arr[2] = arr3; // => 二维数组可以看成一个几行几列的二维表格结构。 for(int i=0;i<arr.length;i++){ System.out.println(arr[i]); } } } |
访问二维数组的元素和遍历
// 访问二维数组 arr[0][0] = 100; //System.out.println(Arrays.toString(arr)); // 二维数组的遍历 for(int i=0;i<arr.length;i++){ for(int j=0;j<arr[i].length;j++){ System.out.print(arr[i][j] + "\t"); } System.out.println(); } |
结论:
【1】二维数值本质上是一维数组,其中的元素也是一维数组。
【2】可以把二维数组看出几行几列的表格结构。
二维数组的字面量声明方式
声明规则的二维数组
import java.util.Arrays; public class Test{ public static void main(String[] args){ // 声明一个具有3行4列的二维数组 int[][] arr = new int[3][4]; // 访问二维数组 arr[0][0] = 100; arr[0][1] = 2; arr[0][2] = 3; arr[0][3] = 4; arr[1][0] = 1; arr[1][1] = 2; arr[1][2] = 3; arr[1][3] = 4; for(int i=0;i<arr.length;i++){ for(int j=0;j<arr[i].length;j++){ System.out.print(arr[i][j] + "\t"); } System.out.println(); } } } |
字面量声明二维数组:
import java.util.Arrays; public class Test{ public static void main(String[] args){ int[][] arr = { {100,2,3,4}, {1,2,3,4}, {1,2} }; for(int i=0;i<arr.length;i++){ for(int j=0;j<arr[i].length;j++){ System.out.print(arr[i][j] + "\t"); } System.out.println(); } } } |