数组
数组的基本概念
所谓数组,是有序的元素序列。说简单点:数组就是一个容器,存放一组相同数据类型的容器。
数组的特点
1.数组是相同数据类型的元素的集合。
2.数组中的各元素的存储是有先后顺序的,它们在内存中按照这个先后顺序连续存放在一起。3.数组元素用整个数组的名字和它自己在数组中的顺序位置来表示。例如,a[0]表示名字为a 的数组中的第一个元素,可以用**数组名[下标/索引]**来访问数组中的元素。
4.数据类型可以是八大基本数据类型,也可以是引用类型。
数组的初始化
1.静态初始化
静态初始化又分为两种格式:
格式一: 数据类型[] 数组名 = {元素1,元素2,元素3,元素4,元素5,...元素n};
格式二: 数据类型[] 数组名 = new int[]{元素1,元素2,元素3,元素4,元素5,...元素n};
初始化的同时为每一个元素给出初始值,可以不指定数组的长度,系统会根据元素的个数去动态计算数组的长度
// 数据类型[] 数组名 = {元素1,元素2,元素3,元素4,...元素n};
int[] arr2 = { 12, 22, 32, 42 };
// 格式二: 数据类型[] 数组名 = new int[]{元素1,元素2,元素3,元素4,...元素n};
int[] arr3 = new int[] { 11, 22, 33, 44, 55, 66 };
2.动态初始化
数据类型[] 数组名 = new 数据类型[数组的大小];
可以采用以很多种方式初始化
// 通过键盘输入
Scanner input = new Scanner(System.in);
for (int i = 0; i < arr.length; i++) {
System.out.print("请输入第" + (i + 1) + "个元素: ");
arr[i] = input.nextInt();
}
// 通过随机数初始化
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) (Math.random() * 10);
}
数组的传递
因为数组传递的是地址,那么通过地址改变了堆区空间的数值,将会影响到所有指向该堆区的引用
public class ArrayDemo {
public static void main(String[] args) {
//
// int[] arr = {11, 22, 33};
// System.out.println("方法调用前数组的所有元素的值: " + Arrays.toString(arr)); // [11, 22, 33]
//
// change(arr);
// System.out.println("方法调用后数组的所有元素的值: " + Arrays.toString(arr)); // [11, 300, 22]
int[] arr = {11, 22, 33}; // [11, 200, 33]
int[] arr2 = {44, 55, 66}; // [44, 55, 66]
arr[1] = 200;
int[] arr3 = arr; // [11, 200, 33]
System.out.println(Arrays.toString(arr)); // [11, 200, 33]
System.out.println(Arrays.toString(arr2)); // [44, 55, 66]
System.out.println(Arrays.toString(arr3)); // [11, 200, 33]
arr3[2] = 400;
System.out.println(Arrays.toString(arr)); // [11, 200, 400]
System.out.println(Arrays.toString(arr2)); // [44, 55, 66]
System.out.println(Arrays.toString(arr3)); // [11, 200, 400]
}
public static void change(int[] arr) {
arr[1] = 300;
System.out.println("方法中数组的所有元素的值: " + Arrays.toString(arr)); // [11, 300, 33]
}
}
for each
foreach遍历方式的特点:
- 1.简化了遍历
- 2.foreach没有索引
- 3.foreach底层还是使用了普通for遍历
编译时期系统会读取foreach的格式,转化普通for格式
public static void main(String[] args) {
int[] arr={5,0,0,6,6,0,5,4,7,6,7,0,5};
//for(元素类型 元素变量 : 遍历对象){
// 使用元素变量
//}
for(int a:arr) {
System.out.print(a+" ");
}
}
排序
冒泡排序
升序排序
1.比较相邻的元素,如果第一个比第二个大,交换两个元素。
2.从第一个元素开始重复1的工作,两两比较直到第一轮结束,此时最右边一个数最大。
3. 对序列中的前 n-1 个元素重复 1,2 的工作,此时右边2个数是最大且已排序。
4. 每一轮都会减少一个数字在比较序列中,共比较 n-1 轮。
public static void main(String[] args) {
int[] arr = {24, 69, 80, 55, 13};
System.out.println("排序前: " + Arrays.toString(arr));
// for (int i = 0; i < arr.length - 1 - 0; i++) {
// /*
// * arr[0] arr[1]比较
// * arr[1] arr[2]比较
// * arr[2] arr[3]比较
// * arr[3] arr[4]比较
// */
// if (arr[i] > arr[i + 1]) {
// int temp = 0;
// temp = arr[i];
// arr[i] = arr[i+1];
// arr[i+1] = temp;
// }
// }
// System.out.println("第一趟排序后: " + Arrays.toString(arr));
//
// for (int i = 0; i < arr.length - 1 - 1; i++) {
// /*
// * arr[0] arr[1]比较
// * arr[1] arr[2]比较
// * arr[2] arr[3]比较
// */
// if (arr[i] > arr[i + 1]) {
// int temp = 0;
// temp = arr[i];
// arr[i] = arr[i+1];
// arr[i+1] = temp;
// }
// }
// System.out.println("第二趟排序后: " + Arrays.toString(arr));
//
// for (int i = 0; i < arr.length - 1 - 2; i++) {
// /*
// * arr[0] arr[1]比较
// * arr[1] arr[2]比较
// */
// if (arr[i] > arr[i + 1]) {
// int temp = 0;
// temp = arr[i];
// arr[i] = arr[i+1];
// arr[i+1] = temp;
// }
// }
// System.out.println("第三趟排序后: " + Arrays.toString(arr));
//
// for (int i = 0; i < arr.length - 1 - 3; i++) {
// /*
// * arr[0] arr[1]比较
// */
// if (arr[i] > arr[i + 1]) {
// int temp = 0;
// temp = arr[i];
// arr[i] = arr[i+1];
// arr[i+1] = temp;
// }
// }
// System.out.println("第四趟排序后: " + Arrays.toString(arr));
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]) {
int temp = 0;
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
System.out.println("排序后: " + Arrays.toString(arr));
}
降序排列
降序排列和升序排列的区别在于:升序排列是在比较那个元素大,而降则序是在比较那个元素小
选择排序
升序排序
1.在待排序的序列中选出最小的元素,将它与第一个元素交换,待排序元素排除第一个元素
2.在待排序的序列中选出最小的元素,将它与第二个元素交换,待排序元素排除第二个元素
3.以此类推,直到待排序的序列中只剩下一个元素。
public static void main(String[] args) {
int[] arr={12,78,87,11,94};
//将数组中的除开第一个元素外每一个元素都于第一个比较如果这个数小于第一个元素那么就把这两个元素交换位置,
//这样数组最开始的那个元素就是最小的了
//然后再将数组中的第二个元素于于第二个元素后面的元素进行比较把最小元素于第二个元素交换位置
//这样数组中第二个元素就比后面的元素都小了,、
//以这种方式比较arr.lenght-1次
for(int i=0;i<arr.length;i++) {
for(int a=i+1;a<arr.length;a++) {
if(arr[a]<arr[i]) {
int temp = arr[i];
arr[i]=arr[a];
arr[a]=temp;
}
}
}
System.out.println(Arrays.toString(arr));
}
二分法查找
1.二分法查找只适用于已经排好序的数组,但是他的速度比普通的遍历查找要快很多
public static void main(String[] args) {
int num=22;
int[] arr={12,22,67,88,94};
int max =arr.length-1; //定义数组中的最大索引
int min = 0;//定义数组中的最小索引
int mid = (min+max)/2; //计算数组中的中间索引
while(arr[mid]!=num) {//用数组中间的元素于要查找的数值进行比较
if(arr[mid]<num) {
min =mid+1; //元素比数值小那么重新定义最小索引
}
else if(arr[mid]>num) {
max =mid-1; //元素比数值大那么重新定义最大索引
}
if(min>max) { //如果min大于max则数组中没有该数值
System.out.println("数组中没有该数值!");
return;
}
mid = (min+max)/2; //从新计算数组中的中间索引
}
System.out.println("该数值在数组中的位置是:"+(mid+1));
}
}
Arrays工具类
public static void main(String[] args) {
int[] arr = {22, 11, 66, 88, 99, 44};
// Arrays的遍历输出方法
System.out.println(Arrays.toString(arr));
// Arrays的排序方法
// Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
// Arrays的二分法查找方法
int index = Arrays.binarySearch(arr, 88);
System.out.println(index);
// System的arraycopy方法,这是一个本地方法,底层不由Java实现,由C语言实现
int[] dest = {100, 200, 300};
// Object src, int srcPos,Object dest, int destPos, int length
System.arraycopy(arr, 1, dest, 0 ,3);
System.out.println(Arrays.toString(dest));
// 复制数组
int[] newArr = Arrays.copyOf(arr, arr.length);
System.out.println(Arrays.toString(newArr));
// 数组扩容
int[] newArr2 = Arrays.copyOf(arr, arr.length + 1);
System.out.println(Arrays.toString(newArr2));
// 缩小数组的容量
int[] newArr3 = Arrays.copyOf(arr, arr.length - 2);
System.out.println(Arrays.toString(newArr3));
// 填充数组
// Arrays.fill(arr, 100);
// System.out.println(Arrays.toString(arr));
// 填充数组的一部分 左闭右开原则
// Arrays.fill(arr, 2, 4, 100);
// System.out.println(Arrays.toString(arr));
int[] copyArr = Arrays.copyOfRange(arr, 2, 5);
System.out.println(Arrays.toString(copyArr));
int[] arr1 = {11, 22, 33, 44};
int[] arr2 = {11, 22, 33, 44};
System.out.println(Arrays.equals(arr1, arr2));
}
}
数组的增删查改
public static void main(String[] args) {
srcArr = new int[] {11, 22, 33, 44};
System.out.println(Arrays.toString(srcArr));
add(55);
System.out.println(Arrays.toString(srcArr));
add(66);
System.out.println(Arrays.toString(srcArr));
insert(srcArr.length, 100);
System.out.println(Arrays.toString(srcArr));
remove(6);
System.out.println(Arrays.toString(srcArr));
System.out.println(get(0));
set(1, 200);
System.out.println(Arrays.toString(srcArr));
}
/*
* 动态扩容的原理
* 往数组中动态添加一个元素
* 返回值类型: void
* 参数列表: int num
* 方法名: add
*/
/*public static void add(int num) {
// 利用System.arraycopy方法处理
int[] descArr = new int[srcArr.length + 1];
// 复制数组
System.arraycopy(srcArr, 0, descArr, 0, srcArr.length);
// 将num赋值到目标数组的最后一个位置
descArr[descArr.length - 1] = num;
// 地址传递
srcArr = descArr;
}*/
public static void add(int num) {
int[] descArr = Arrays.copyOf(srcArr, srcArr.length + 1);
descArr[descArr.length - 1] = num;
srcArr = descArr;
}
/*
* 往数组的任意位置插入一个元素
* 返回值类型: void
* 参数列表: int index, int num
* 方法名: insert
*/
public static void insert(int index, int num) {
int[] descArr = new int[srcArr.length + 1];
System.arraycopy(srcArr, 0, descArr, 0, index);
descArr[index] = num;
System.arraycopy(srcArr, index, descArr, index + 1, srcArr.length - index);
srcArr = descArr;
}
/*
* 将数组中的某个索引处的元素删除
* 返回值类型: void
* 参数列表: int index
* 方法名: remove
*/
public static void remove(int index) {
int[] descArr = new int[srcArr.length - 1];
System.arraycopy(srcArr, 0, descArr, 0, index);
System.arraycopy(srcArr, index + 1, descArr, index, descArr.length - index);
srcArr = descArr;
}
public static int get(int index) {
return srcArr[index];
}
public static void set(int index, int num) {
srcArr[index] = num;
}
多维数组
1.多维数组本质也是一维数组,本质就是存放了一维数组的数组。
2.格式1:
-
数据类型[] 数组名 = new 数据类型[数组的长度];
-
数据类型[][] 数组名 = new 数据类型[m][n];
-
m: 二维数组中一维数组的长度
-
n: 每一个一维数组中元素的个数
-
int[][] arr = new int[3][2];//表示arr中有3个一维数组,每一个一维数组有2个元素
- 3.变式:
-
数据类型 数组名[][] = new 数据类型[m][n];
-
数据类型[] 数组名[] = new 数据类型[m][n];
*4.格式2:
-
数组类型[][] 数组名 = new 数据类型[m][];
-
m: 二维数组中一维数组的长度
-
n: m必不可少,n可省略,表示每一个一维数组的元素个数不确定
-
可以后期动态地改变每一个一维数组元素的个数
public static void main(String[] args) {
int[][] arr = new int[3][2];
int[] arr2[] = new int[3][3];
int[] x,y[],z[][]; // 1
int n[] = new int[2],i,j,k;
/*
* int n[] = new int[2];
* int i;
* int j;
* int k;
*/
int[] x,y[],z[][];// 表示1个一维数组,1一个二维数组,1个三维数组
// int[] x;
// int[] y[];
// int[] z[][];
}
二维数组的遍历思想
public static void main(String[] args) {
int[][] arr = {{11,22,33}, {44,55}, {66,77,88,99}};
//二维数组的静态初始化
// 遍历第一个一维数组
//System.out.println(arr[0][0]);
//System.out.println(arr[0][1]);
//System.out.println(arr[0][2]);
//for (int i = 0; i < arr[0].length; i++) {
// System.out.println(arr[0][i]);
//}
// 遍历第二个一维数组
//System.out.println(arr[1][0]);
//System.out.println(arr[1][1]);
//for (int i = 0; i < arr[1].length; i++) {
// System.out.println(arr[1][i]);
//}
// 遍历第三个一维数组
//System.out.println(arr[2][0]);
//System.out.println(arr[2][1]);
//System.out.println(arr[2][2]);
//System.out.println(arr[2][3]);
//for (int i = 0; i < arr[2].length; i++) {
// System.out.println(arr[2][i]);
//}
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.println(arr[i][j]);
}
}
}