一、数组基础、使用、操作
package DataStructures;
import java.util.*;
public class Array_array {
/*
* 数组
* 定义:数组是一组同种类型的数据的集合
* Note:
* 1.数组的下标索引是从0开始
* 2.数组中的元素可以是任意数据类型,但是所有的元素的类型相同,例如int,float,double,char,String等
* 3.常用一维和二维数组,其他的高维数组不经常用,但是使用方法类似
* 4.数组是引用数据类型,引用数据类型使用之前要进行声明以及初始化。数组变量不是数组本身,而是指向堆内存中的数组对象
* 5.声明一个数组将在内存空间中为其分配一个连续空间,数组的名字代表的是这连续空间的首地址,通过首地址能访问数组中所有元素
* 6.数组的使用:声明数组、初始化(分配空间以及赋值)、操作数组
* 7.int[] 就是一种数据类型,与 int 类型、String 类型相似,一样可以使用该类型来定义变量,也可以使用该类型进行类型转换等。
* 使用 int[] 类型来定义变量、进行类型转换时与使用其他普通类型没有任何区别。int[] 类型是一种引用类型,创建 int[] 类型的
* 对象也就是创建数组,需要使用创建数组的语法。
*/
public static void main(String[] args) {
//数组的定义和初始化
//1.声明数组,指定数组的元素类型
/*
* Note:
* 1.声明数组变量的时候有两种方式,但是java中更推荐第一种([]括号在元素数据类型之后)
* 2.不要忘记括号
* 3.此时只是声明数组变量,不需要给定数组的大小
*/
//以int类型数组为例
int[] ar_i_1;
int ar_i_2[];
//2.分配空间
/*
* Note:
* 1.声明数组后,要给数组变量分配存储空间,使用new关键字进行空间分配
* 2.[]中为数组长度,当确定数组的大小后,不能更改,且数组长度时必须的
* 3.当确定数组的长度后,系统根据数据中的元素的数据类型对数组分配初始值
* (1)byte\short\int\long --- 0
* (2)float\double --- 0.0
* (3)char --- \u0000
* (4)boolean --- false
* (5)引用类型(类、接口、数组) --- null
*/
ar_i_1 = new int[2];
ar_i_2 = new int[5];
//3.赋值
/*
* Note:
* 1.数组是一个有序的集合,除了对数组中单个元素单独的赋值,可以通过循环对数组元素进行赋值(操作)
*/
ar_i_1[0] = 11;
ar_i_1[1] = 12;
for(int i = 0; i < 5; i++) {
ar_i_2[i] = i;
}
//数组其他初始化方式
/*
* Note:
* 1.数组初始化可以分为两种方式:静态初始化和动态初始化
* (1)静态初始化:初始化时由程序员显示的指定数组元素的初始值,由系统决定数组长度
* (2)动态初始化:初始化有程序员指定数组长度,由系统为数组元素分配初始值
*/
//可以将1和2同时进行,之后再对数组进行赋值
int[] ar_i_3 = new int[5];
//创建数组时同时对数组中元素赋值(使用new)
/*
* Note:
* 1.这种初始化方式,不需要指定数组长度,如果指定数组长度并进行赋值,会报错
*/
int[] ar_i_4 = new int[] {1,2,3};
//创建数组时同时对数组中元素赋值(不使用new)
/*
* Note:
* 1.使用这种方式时,声明和初始化要同时进行,不能分开(不能省略数组变量的类型)
* int[] ar_i_5;
* ar_i_5 ={1,2,3};
*/
int[] ar_i_5 = {1,2,3};
//二维数组
/*
* Note:
* 1.二维数组的定义和初始化差不多,就不想详细解释
* 2.二维数组是存储一维数组的数组,即每个元素是一个数组
* 3.二维数组可以是不规则的,即每个元素为一个一维数组,每个一维数组的长度可以不一样
*/
char[][] ar_c1;
char ar_c2[][];
char[][] ar_c3 = new char[][] {{'1','2'},{'3','4'}};//定义时初始化
char[][] ar_c4 = new char[][] {{'1','2'},{'1','2','3'}};//定义时初始化
char[][] ar_c5 = new char[2][3];//定义并给定空间,随后进行初始化
char[][] ar_c6 = new char[2][];//数组的二维长度为空,可以变化
//数组元素的操作
/*
* Note:
* 1.java.util包中的Array类包含了操作数组的各种方法,可以直接调用相关的方法,想要了解更多和详细的,可以查看java的API文档
* 2.关于对数组的操作,可以根据实际情况或者应用进行变换
*/
//数组有一个length属性,可以获得数组的长度
int len_ar = ar_i_1.length;
//数组的遍历或获取数组元素(数组元素查询)
//获取全部元素(遍历整个数组)
/*
* Note:
* 1.一维数组需要一重循环;二维数组需要二重循环....
*/
int[] arr1 = new int[] {1,2,3,4,5,6,1,2,3};
int[][] arr2 = new int[][] {{11,12,13},{21,22}};
PrintAllElement1(arr1);
PrintAllElement2(arr2);
//获取数组的单个元素
//已知元素的位置,获取该位置元素的值
int arr1_value = SelectElementValue1(arr1, 2);
System.out.println(arr1_value);
int arr2_value = SelectElementValue2(arr2, 1, 1);
System.out.println(arr2_value);
//已知元素的值,获取元素所在的位置
/*
* Note:
* 1.一般通过值查找数组中该元素的位置时,如果数组中存在重复的元素的值,就会有多个位置,有的方法是返回查找的到的第一个元素
* 的位置,可以根据需求来更改算法。
* 2.返回的是数组的索引,如果需要的数组重元素的位置,需要进行变换
* 3.当数组较大时,遍历整个数组耗费时间较长,故可以其他方法减少查找的时间,如二分查找等
*/
int arr1_pos = SelectElementPosition1(arr1, 2);
System.out.println(arr1_pos);
int[] arr2_pos = new int[2];
arr2_pos = SelectElementPosition2(arr2, 12);
System.out.println(arr2_pos[0] + " " + arr2_pos[1]);
//数组扩容(数组元素增加)
/*
*
* Note:
* 1.创建数组后,数组的大小不能更改,但申请一个较大的空间,会造成空间的浪费
* 2.扩容方法:思想就是创建一个新的长度的数组,并将原来的数组复制过去
* (1)通过创建新的数组同时增加数组的长度
* (2)Arrays.copyOf(原数组名,新的数组的长度)
* (3)System.arraycopy(原数组名,起始下标,新数组名,起始下标,复制长度)
*/
int[] arr3 = new int[10];
arr3 = ArrayCapacity(arr1, 10);
for(int i = 0; i < arr3.length; i++)
System.out.print(arr3[i] + " ");
System.out.println();
int[] arr4 = Arrays.copyOf(arr1, 10);
for(int i = 0; i < arr4.length; i++)
System.out.print(arr4[i] + " ");
System.out.println();
int[] arr5 = new int[20];
System.arraycopy(arr1, 0, arr5, 0, arr1.length);
for(int i = 0; i < arr5.length; i++)
System.out.print(arr5[i] + " ");
System.out.println();
//数组元素删除
/*
* Note:
* 1.数组元素被删除后,数组的长度发生变化,可以根据数组扩容的思想进行相应的操作(需要新的存储空间),也可以进行覆盖(不许新的存储空间)
* 2.第一种方法简单容易理解,删除元素后,数组还保持原先的顺序,但是需要开辟新的存储空间,而且需要知道新的开辟的空间的大小
* 3.第二种方法是通过删除这个元素后,后边的元素去覆盖这个位置的元素
* (1)有序:被删除位置元素之后的元素依次向前移动进行覆盖
* (2)无序:可以选择从数组最后边选择元素进行覆盖
* 4.可以根据索引删除数组元素,也可以根据元素值删除
* (1)根据索引删除,可以明确知道删除元素的个数
* (2)根据元素的值来删除数组元素(删除的元素有多个重复的,使用创建新数组的方法不知道新数组的大小,使用覆盖的方法会更方便)
*/
int[] arr6 = new int[arr1.length - 1];
arr6 = RemoveElement1(arr1, 1);
PrintAllElement1(arr6);
int arr_po = RemoveElement2(arr1, 1);
for(int i = 0; i < arr1.length - arr_po; i++)
System.out.print(arr1[i] + " ");
System.out.println();
//数组元素修改
/*
* Note:
* 大多数情况下是根据索引进行数组元素的值的修改,其他情况以后想到了在更新
*/
arr1[1] = 9;
for(int i = 0; i < arr1.length; i++)
System.out.print(arr1[i] + " ");
System.out.println();
//数组复制
/*
* Note:
* 1.使用循环,一个一个元素的赋值
* 2.System.arraycopy()
* 3.Arrays.copyOf()
* 4.Object.clone()
* 效率:System.arraycopy() > Object.clone() > Arrays.copyOf() > 循环
* 1、2、3之前都用到过,就省略了,主要说说4
*/
int[] arr7 = new int[9];
arr7 = arr1.clone();
for(int i = 0; i < arr7.length; i++)
System.out.print(arr7[i] + " ");
System.out.println();
/*
* Note:
* 还有一些会用直接赋值的方法,这是对数组的引用,指向同一个数组(对象),当对数组进行修改时,原数组也会发生变化
*/
int[] arr8;
arr8 = arr1;
for(int i = 0; i < arr8.length; i++)
System.out.print(arr8[i] + " ");
System.out.println();
//Object.hashCode() 默认返回内存地址
System.out.println(arr1.hashCode());
System.out.println(arr8.hashCode());
//数组连接
/*
* Note:
* 根据需求的不同可以进行数组合并,简单的数组合并、去重合并、排序合并、去重并排序合并等等;
* 这里就简单的进行合并,后面可以根据需求进行合并;
* 合并的方法也有很多种,这里就根据前面提到的进行合并
*/
int[] arr9 = new int[] {9,8,7,6};
int[] arr10 = new int[arr1.length + arr9.length];
//将arr1数组复制到arr10中
System.arraycopy(arr1, 0, arr10, 0, arr1.length);
//将arr9数组复制到arr10中,接着arr1
System.arraycopy(arr9, 0, arr10, arr1.length, arr9.length);
for(int i = 0; i < arr10.length; i++)
System.out.print(arr10[i] + " ");
System.out.println();
//数组反转
/*
* Note:
* 1.可以将数组倒序复制到新的数组中
* 2.可以将数组的首尾相应元素互换,直至数组倒序
*/
int[] arr11 = new int[9];
arr11 = ReverseArray1(arr1);
for(int i = 0; i < arr11.length; i++)
System.out.print(arr11[i] + " ");
System.out.println();
int[] arr12 = new int[9];
arr12 = ReverseArray2(arr1);
for(int i = 0; i < arr12.length; i++)
System.out.print(arr12[i] + " ");
System.out.println();
//数组比较
/*
* Note:
* 数组比较(是否相等,数组大小等),可以通过循环对相应位置的元素逐一比较,但是不能直接arr1==arr9进行比较
* java中Arrays类提供了比较的方法,可以直接调用
*/
System.out.println(Arrays.equals(arr1, arr9));
//数组排序
/*
* Note:
* 数组排序,有很多的方法,之后会专门在复习相关的排序算法,这里就不多讲了
* java中Arrays类提供了排序的方法,可以直接调用
*/
Arrays.sort(arr1);
for(int i = 0; i < arr1.length; i++)
System.out.print(arr1[i] + " ");
System.out.println();
//数组中经常出现的异常
/*
* Note:
* 1.NullPointerException 空指针异常
* 原因:引用类型变量没有指向任何对象,而访问了对象的属性或者是调用了对象的方法
* 2.ArrayIndexOutOfBoundsException 索引值越界
* 原因:访问了不存在的索引值。
*/
}
//获得一维数组全部的元素
public static void PrintAllElement1(int[] arr) {
for(int i = 0; i < arr.length; i++)
System.out.print(arr[i] + " ");
System.out.println();
}
//获得二维数组全部的元素
public static void PrintAllElement2(int[][] arr) {
for(int i = 0; i < arr.length; i++) {
for(int j =0 ; j < arr[i].length ; j++ ) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
//查找数组中的元素---一维数组(已知位置,查找值)
/*
* Note:
* 我们的习惯是从1开始,但是数组中是从0开始,要进行换算
*/
public static int SelectElementValue1(int[] arr, int pos) {
int value = arr[pos - 1];
return value;
}
//查找数组中的元素---二维数组(已知位置,查找值)
public static int SelectElementValue2(int[][] arr, int xpos, int ypos) {
int value = arr[xpos - 1][ypos - 1];
return value;
}
//查找数组中的元素---一维数组(已知值,查找位置(返回第一个元素的位置))
public static int SelectElementPosition1(int[] arr, int value) {
int pos = 0;
for(int i = 0; i < arr.length; i++) {
if(arr[i] == value) {
pos = i;
break;
}
}
//返回的是元素在数组中的索引
return pos;
}
//查找数组中的元素---二维数组(已知位置,查找值)
public static int[] SelectElementPosition2(int[][] arr, int value) {
int[] pos = new int[2];
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++) {
if(arr[i][j] == value) {
pos[0] = i;
pos[1] = j;
break;
}
}
}
return pos;
}
//数组扩容--第二个参数是扩容数组的长度
public static int[] ArrayCapacity(int[] arr, int len) {
int[] arr1 = new int[len];
for(int i = 0; i < arr.length; i++) {
arr1[i] = arr[i];
}
return arr1;
}
//删除元素--根据索引删除
public static int[] RemoveElement1(int[] arr, int pos) {
//根据索引删除元素,传入几个索引就减去几个空间(Note:可以加入判断索引值是否越界)
int[] arrNew = new int[arr.length - 1];
int j = 0;
for(int i = 0; i < arr.length; i++) {
if(i != pos) {
arrNew[j] = arr[i];
j++;
}
}
return arrNew;
}
//删除元素--根据元素删除
public static int RemoveElement2(int[] arr, int ele) {
int pos = 0;
for(int i = 0; i < arr.length; i++) {
if(arr[i] == ele) {
pos++;
for(int j = i; j < arr.length - pos; j++) {
arr[j] = arr[j + 1];
}
}
}
return pos;
}
//数组逆序(反转)--法一
public static int[] ReverseArray1(int[] arr) {
int[] arrNew = new int[arr.length];
int j = 0;
for(int i = arr.length - 1; i >= 0; i--) {
arrNew[j] = arr[i];
j++;
}
return arrNew;
}
//数组逆序(反转)--法二
public static int[] ReverseArray2(int[] arr) {
for(int i = 0; i < arr.length; i++) {
int temp;
temp = arr[i];
arr[i] = arr[arr.length - 1 - i];
arr[arr.length - 1 - i] = temp;
}
return arr;
}
}
二、Arrays类
1.简介
该类包含用于操作数组的各种方法(如排序和搜索)。 该类还包含一个静态工厂,可以将数组视为列表。如果指定的数组引用为空,则该类中的方法都抛出一个NullPointerException
,除非另有说明。如果想要看更详细的内容可以查看java的API文档。
static String |
toString(type[] a) 返回指定数组的内容的字符串表示形式。 |
static void |
sort(type[] a, int fromIndex, int toIndex) 按照数字顺序排列指定的数组(可以指定范围,默认升序) |
static void |
parallelSort(type[] a,int fromIndex, int toIndex) 按照数字顺序排列指定的数组(可以指定范围) |
static int |
hashCode(type[] a) 根据指定数组的内容返回哈希码 |
static void |
fill(type[] a, int fromIndex, int toIndex, type val) 将指定类型的元素分配给指定数组的每个元素(可以指定范围) |
static boolean |
equals(type[] a, type[] a2) 如果两个指定的数组彼此 相等 ,则返回 true 。 |
static int[] |
copyOf(int[] original, int newLength) 复制指定的数组,用零截取或填充(如有必要),以便复制具有指定的长度。 |
static int[] |
copyOfRange(int[] original, int from, int to) 将指定数组的指定范围复制到新数组中。 |
static type |
binarySearch(type[] a, type key) 使用二叉搜索算法搜索指定数组的指定值。 |
static type |
binarySearch(type[] a, int fromIndex, int toIndex, type key) 使用二叉搜索算法搜索指定值的指定数组的范围。 |