1、什么是数组:数组就是保存相同类型元素的一个集合。(数组是一个线性表的数据结构) 2、数组的初始化:数组最大的特点就是长度固定,一旦声明创建一个数组之后,长度是固定的,无法修改! (1)数组的动态初始化︰创建数组时,规定长度,数组中每个元素都是其数据类型的默认值 ①语法:数据类型[数组名称= new数据类型[数组长度] | int[] score = new int[10]; //创建了一个保存10个int的int数组,其中每个元素都是int的默认值O | double] sal = new double[20]; //创建了一个保存20个double的double数组,其中每个元素都是double的默认值0.0 (2)数组的静态初始化︰声明并创建数组时,就给对应位置的元素进行赋值 ①语法:数据类型[数组名称={data1,data2,data3 ...dataN} | int[] score ={10,40,70,90}; //此时数组的长度根据初始化数值的个数来定 | int[] score = new int[]{10,30,50}; //静态初始化也可以保留new数据类型[不需要写长度]{} 3、数组的使用:数组在内存中是一块连续的空间,空间的编号从0开始依次递增,这个编号就称为数组的下标,最终访问数组元素就是根据数组名称[下标]来取得对应元素。 (1)用法 | int[] score = {10,30,50,70}; // score数组的下标范围就是[O..4) | score[0] //取得第一个元素的内容 | score[2] //取得第三个元素的内容 (2)表示/存储数组元素时,为何要采用偏移量? · 数组在内存中存储时,空间是连续的,为了方便起见,程序只需要记录数组首元素的地址即可,其他元素的地址通过偏移量可以立即求得!(帮助程序减少存储其他元素地址的开销) (3)取得某个数组的长度,使用数组名称.length属性来取得数组的长度 | system.out.println(score.length); 4、数组的遍历 (1)普通的for循环:可以进行增删改查。
int[] score = {1,3,5,7,9};
for (int i = 0; i < score.length; i++) {
if (i == 2) {
score[i] = 50; //在遍历时修改数组某个元素
}
system.out.print( score[i] +" ");
}
(2)在遍历数组时还可以使用增强的for-each循环来遍历数组∶只能用于数组的元素读取,不能修改数组元素! !! ①语法:for(数据类型 临时变量名称: 数组名称){} ②例子:
int[] score = {1,3,5,7,9};
for (int temp : score) {
system.out.print(temp + " “);
}
(3)若只是进行数组元素的读取,使用for-each循环。若还需要在数组遍历时修改数组元素的内容,只能使用普通for循环 5、数组是引用数据类型 (1)JVM一共将内存划分为6大区域,今天咱们只看堆和栈区 栈:栈区存放方法调用时产生的所有临时变量(形参),局部变量都随着方法调用时的栈帧入栈和出栈(方法调用结束之后,所有的临时变量都会被销毁 堆:只要是关键字new产生的内容,都在堆中存储。只要程序不退出,堆中的数据还在被使用,这个数据就不会被销毁! (2)关于基本数据类型变量和引用数据类型变量的区别 ①基本类型变量保存的都是具体的数值 ②对于引用数据类型变量来说,保存的是对应的对象的地址(堆内存的地址)! | int data = new int[5]; //先在堆中开辟一块连续的内存空间,然后将数组对象的首地址保存给data | int[] data2 = data; //就相当于给数组对象又起了个名字叫data2,没产生新对象 (3)当一个引用数据类型的值为null时,表示该引用不指向任何的内存空间,因此无法使用该引用获取任何数值 | arr1 = null; | System.out.println(arr1); //会报错,NPE异常(NullPointerException) 6、引用数据类型作为方法的参数 (1)回顾之前的swap函数
public static void swap(int[ ] arr) {
int temp = arr[0];
arr[0] = arr[1];
arr[1] = temp; //此时把传入的引用对应的对象更改了,所以会生效
}
(2)swap函数修改一处
public static void swap(int[ ] arr) {
arr = new int[]{30, 40}; //创建了新的对象
int temp = arr[0];
arr[0] = arr[1];arr[1] = temp;//新创建的对象改了,原本的对象没改,所以不生效
}
7、引用作为方法的返回值:返回的是地址 8、数组操作 (1)数组转字符串 ①JDK提供的工具类
int[] data = new int[]{1,2,3};
String str = Arrays.toString(data);
system.out.println(str);
②可以自己写 (2)数组拷贝 ①使用JDK提供的Arrays.copy0f(原数组名称, 新数组长度)方法可以真正复制一个数组(在堆上产生新空间,并将原数组内容拷贝过来)
int[] arr = new int[]{1,2,3};
int[] newArr = Arrays.copyOf(arr,arr.length); //产生了一个一样的新对象
int[] newArr2 = arr; //只是把arr地址给了newArr2,并没产生新对象
②Arrays.copy0f(原数组名称, 新数组长度)关于新数组长度参数 · 当新数组长度==原数组一样,完全拷贝 · 当新数组长度<原数组,部分拷贝,拷贝到指定长度为止 · 当新数组长度>原数组,完全拷贝后面再补齐元素,补齐的元素值是其数据类型的默认值 9、二分查找:二分查找要使用二分查找算法,前提︰要查找的数组必须是一个有序数组!! (1)思想: 每次都和数组的中间位置mid比较 若待查找元素val < mid :则一定小于整个右半区间[mid..n) : 则继续在左半区间查找元素 若待查找元素val == mid,找到了 若待查找元素val > mid : 则大于整个左半区间 : 继续从右半区间开始查找! (2)到底什么时候循环退出? 1.找到了待查找的元素 arr[mid] == val退出 2.l > r(不能取等!!,取等时,待查找区间还有一个元素没有判断)整个区间为空,没找到元素,退出 (3)代码
public static int binSearch(int[] arr,int toFind) {
int 1 = 0; //区间左端
int r = arr.length - 1; //区间右端
while (l <= r){
int mid = l + (r - l)/2; //直接(l+r)/2可能会出现l+r溢出情况
if (arr[mid] == toFind) {
return mid;
}else if (toFind < arr[mid]) {
r = mid - 1;
}else{
l = mid + 1;
}
}
return -1;
}
10、冒泡排序 (1)思想:不断的将前一个元素和后一个元素进行大小比较若前一个元素比后一个元素大,就两两交换彼此元素。 (2)代码
public static void bubbleSort(int[] arr){
boolean isSwap = false;
//只剩一个元素时,就不需排序了,可以少循环一次,所以下面arr.length - 1
for(int i=0;i<arr.length - 1;i++){
for(int j=0;i<arr.length-i - 1;j++){ //多减一个1为了防止下面的j+1越界
if(arr[j] > arr[j+1]){
isSwap = true; //说明进行了交换操作
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
if(!isSwap){
break; //说明没进行交换操作,说明剩下的元素都是有序的,不需要继续排序
}
}
}
11、数组逆置 (1)循环结束条件:设i,j是首位元素 当i == j :待处理区间只剩下一个元素,没有别的可以换的了 当i > j :待处理区间为空 (2)代码
public static void reverse(int[] arr){
int i = 0; //i是首
int i = arr.length - 1; //j是尾
while (i<i){ // i == j,区间只剩下一个元素,退出
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
i--;
}
}
12、二维数组:本质上就是个表格,外层循环表示行,内层循环表示列 (1)语法: 动态初始化: 数据类型[][] 数组名称 = new 数据类型[行数][列数]; 静态初始化: 数据类型[][] 数组名称 = new 数据类型[][]{ {第一行数据}, {第二行数据}, .......... } (2)注意 对于二维数组来说每一行就是一个子数组 arr.length 表示行数(有几个子数组) arr[i] 就是第i行的子数组 arr[i].length 就表示第i行的列元素的长度 arr[i][j] 就表示第i行第j列的元素值
13、动态数组
(1)创建一个动态数组对象: List<数组中保存的类型> 名称 = new ArrayList<>();
List<Integer> list = new ArrayList<>();
· 记得里面写包装类,而不是基本数据类型
(2)相关操作
①向list中添加元素:默认是尾插法
list.add(20); //在尾部添加元素20
②删除指定索引的元素
list.remove(1); //删除索引为1的元素
list remove(内容) //假如是String数组,括号里可以按内容删除,而非索引
③修改指定索引的元素
list.set(1,300); //将索引为1的元素改成300
④查询:
· 在list中取得指定索引位置的元素
list.get(1); //查询索引为1的元素是什么
· 查询list中是否存在所查找的元素,返回值为boolean
list.contains(300); //查询list中有没有值为300的元素