文章目录
数组
介绍
什么是数组
是一种引用数据类型。
是一种常见的数据结构,存储相同数据类型的数据。
使用一个统一的数组名和不同的下标来唯一确定数组中的元素。
是在内存中存储相同数据类型的连续空间。
简单的线性序列,访问速度快。
元素在数组中的排序叫做下标,从0开始。
数组的长度一旦声明,就不能改变了。
数值数组元素的默认值为 0,而引用元素的默认值为 null。
特性
- 一致性:可以保存任何相同数据类型的元素。
- 有序性:元素有序,通过下标访问。
- 不可变性:一旦初始化,长度(元素的个数)不可变。
分类
一维数组
实质上是一组相同类型数据的线性集合,是最简单的一种数组。
声明数组
声明数组的时候不需要定义长度。
但是声明时,类型后边必须跟中括号”[]“。
声明的是存放数组的变量,并没有分配内存空间,还不能使用。
数组类型[] 数组名;(推荐使用,可读性强)
比如:
int[] intArray;//声明一个int类型的数组
String[] strArray;//声明一个string类型的数组
可以使用new来告诉程序为数组分配空间。
数组类型[] 数组名 = new 数组类型[数组长度];
比如:
int[] arr= new int[5];//声明一个int类型的数组,并定义它的长度为5
arr数组在内存中的格式是这样的:
图中的arr是数组的名称,中括号”[]“中的值代表数组的小标,数组中是通过下标来区分元素的,下标从0开始。数组大小一旦声明就不能更改。
当声明一个数组变量时,其实是创建了一个类型为“数据类型[]”(如 int[]、double[]、String[])的数组对象,它具有下表所示的方法和属性:
方法名 | 返回值 |
---|---|
clone() | Object |
equals(Object obj) | boolean |
getClass() | Class<?> |
hashCode() | int |
notify() | void |
notify All() | void |
toString() | String |
wait() | void |
wait(long timeout) | void |
wait(long timeout,int nanos) | void |
length(这个是属性) | int |
初始化数组
数组必须要初始化才能使用,就是为数组元素分配内存空间,并为每个数组元素赋初始值。
为数组元素分配内存空间,其实就是将数组中的元素存储到每个内存空间中,即使内存空间存储的内容为空,它的值就用null。有两种方式获取初始值:
- 1、系统自动分配。
- 2、自定义来指定。
- 1、使用new指定数组大小后初始化:
使用new关键字创建数组,并指定数组的大小。
元素赋值时才能确定值。
//创建数组后,元素的值并不确定,要为数组中的每一个元素赋值,下标从0开始。
数据类型[] 数组名 = new 数据类型[数组长度];
int[] intArray = new int[5];
intArray[0] = 1;
intArray[1] = 2;
intArray[2] = 3;
intArray[3] = 4;
intArray[4] = 5;
如果只指定了数组的长度,系统会自动为数组分配初始值。
- 整数类型(byte、short、int、long),元素值为0。
- 浮点类型(float、double),元素值为0.0。
- 字符类型(char),元素值为’\u0000’。
- 布尔类型(Boolean),元素值为false。
- 引用类型(类、接口、数组),元素值为null。
- 2、使用new指定数组元素的值
初始化的时候就指定元素的值。
这时中括号中不指定数组的长度。
数据类型[] 数组名 = new 数据类型[]{值1,值2,值3,....};
int[] intArray = new int[]{1,2,3,4,5};
注意:
- 不能在进行数组初始化时,既指定长度又指定元素的值,
int[] intArray = new int[5]{1,2,3,4,5};
这样编译报错。Cannot define dimension expressions when an array initializer is provided
- 3、直接指定数组元素的值
不使用new关键字。
数据类型[] 数组名 = {值1,值2,值3,.....};
int[] intArray = {1,2,3,4,5};
注意:
- 数组的声明和初始化要同步,
int[] intArray ; intArray = {1,2,3,4,5};
这样会编译错误,Array constants can only be used in initializers
获取元素
通过下标获取元素。
- 获取单个元素
- 适合数组元素数量不多的时候。
int[] arr = {1,2,3,4,5};
System.out.println("获取数组arr中的第一个元素:"+arr[0]);//获取数组arr中的第一个元素:1
System.out.println("获取数组arr中的第三个元素:"arr[2]);//获取数组arr中的第三个元素:3
System.out.println("获取数组arr中的第六个元素:"+arr[5]);//运行错误,数组下标越界:java.lang.ArrayIndexOutOfBoundsException
注意:
- 数组的下标超过了(数组的长度-1)时,会出现运行时错误:
数组下标越界:java.lang.ArrayIndexOutOfBoundsException
- 遍历数组(获取数组中的所有元素)
可以获取数组的全部元素。
适合数组中元素比较多的时候。
int[] arr = {1,2,3,4,5};
for (int i = 0; i < arr.length; i++) {
System.out.println("第"+i+"个元素是:"+arr[i]);
}
运行结果为:
第1个元素是:1
第2个元素是:2
第3个元素是:3
第4个元素是:4
第5个元素是:5
int[] arr = {1,2,3,4,5};
for (int i : arr) {
System.out.println("元素的值依次是:"+i);
}
运行结果为:
元素的值依次是:1
元素的值依次是:2
元素的值依次是:3
元素的值依次是:4
元素的值依次是:5
二维数组
二维数组被称作数组的数组,就是数组里边定义了数组。
特殊的一维数组,数组中的元素又是一个一维数组。
声明二维数组
数据类型[][] 数组名;//第一个中括号表示行,第二个中括号表示列。
int[][] intArray;
初始化二维数组
- 1、使用new指定大小后初始化
数据类型[][] 数组名 = new 数据类型[外层数组长度][内层数组长度];
int[][] arr1 = new int[2][2];//定义int类型2行2列的二位数组
arr1[0][0] = 1;
arr1[0][1] = 2;
arr1[1][0] = 3;
arr1[1][1] = 4;
二维数组内存结构图:
- 2、使用new指定数组元素的值
这时候不指定数组的长度。
数据类型[][] 数组名 = new 数据类型[][]{{值1,值2,...},{值1,值2,...},...};
int[][] arr2 = new int[][]{{1,2},{3,4}};//2行2列的二维数组,并指定了元素的值
注意:
- 使用new初始化二位数组的时候,不能既指定长度又指定元素的值,
编译错误:Cannot define dimension expressions when an array initializer is provided
- 3、直接指定数组元素的值
数据类新[][] 数组名 = {{值1,值2,...},{值1,值2,...},...};
int[][] arr3 = {{1,2},{3,4}};//2行2列的二维数组
获取元素
通过下标获取。
行和列的下标都是从0开始。
- 获取单个元素
int[][] arr3 = {{1,2,3,},{4,5,6,7}};
System.out.println("第1行1列的值:"+arr3[0][0]);
System.out.println("第2行3列的值:"+arr3[1][2]);
System.out.println("第3行1列的值:"+arr3[2][0]);//运行报错:数组下标越界了
运行结果为:
第1行1列的值:1
第2行3列的值:6
java.lang.ArrayIndexOutOfBoundsException
- 遍历数组
arr.length
获取的是数组的行数,arr[i].length
获取的是该行的列数,也就是元素数。
//for循环遍历
int[][] arr3 = {{1,2,3},{4,5,6,7}};
for (int i = 0; i < arr3.length; i++) {
for (int j = 0; j < arr3[i].length; j++) {
System.out.println("第 "+(i+1)+" 行第 "+(j+1)+" 列的值是:"+arr3[i][j]);
}
System.out.println("上边是第 "+(i+1)+" 行的元素值");
}
运行结果为:
第 1 行第 1 列的值是:1
第 1 行第 2 列的值是:2
第 1 行第 3 列的值是:3
上边是第 1 行的元素值
第 2 行第 1 列的值是:4
第 2 行第 2 列的值是:5
第 2 行第 3 列的值是:6
第 2 行第 4 列的值是:7
上边是第 2 行的元素值
//for each循环遍历
int[][] arr3 = {{1,2,3},{4,5,6,7}};
for (int[] is : arr3) {
for (int i : is) {
System.out.println(i);
}
}
运行结果为:
1
2
3
4
5
6
7
快速打印输出二维数组
int[][] arr3 = {{1,2,3},{4,5,6,7}};
System.out.println(Arrays.deepToString(arr3));
运行结果为:
[[1, 2, 3], [4, 5, 6, 7]]
多维数组
多维数组其实就是相当于几维数组,就有几个中括号。
其实二维数组也是多维数组。
声明多维数组
数据类型[][][].. 数组名;
int[][][] arr;
初始化多维数组
int[][][] arr1 = new int[2][3][4];//三层数组,从外往里数:第一层有两个元素,第二层有三个元素,第三层有四个元素。
int[][][] arr2 = new int[][][]{
{//第一层的第一个元素
{1,2,3,4},
{5,6,7,8,},
{9,10,11,12}
},
{//第一层的第二个元素
{13,14,15,16},
{17,18,19,20},
{21,22,23,24}
}
};
for (int i = 0; i < arr2.length; i++) {
for (int j = 0; j < arr2[i].length; j++) {
for (int j2 = 0; j2 < arr2[i][j].length; j2++) {
System.out.print(arr2[i][j][j2]+",");
}
System.out.println("最内层==="+arr2[i][j].length+"个");
}
System.out.println("第二层===="+arr2[i].length+"个");
}
System.out.println("最外层====="+arr2.length+"个");
运行结果为:
1,2,3,4,最内层===4个
5,6,7,8,最内层===4个
9,10,11,12,最内层===4个
第二层====3个
13,14,15,16,最内层===4个
17,18,19,20,最内层===4个
21,22,23,24,最内层===4个
第二层====3个
最外层=====2个
遍历
- for循环
- 增强for循环(for-each)
- Arrays.toString(数组名)方法
public static void main(String[] args){
int[] arr = {1,2,3,4,5};
//for循环
for (int i = 0; i < arr.length; i++) {
System.out.print(i+" ");
}
System.out.println();
//增强for循环(for-each)
for (int i : arr) {
System.out.print(i+" ");
}
System.out.println();
//Arrays.toString()
String str = Arrays.toString(arr);
System.out.println(str);
}
运行结果为:
0 1 2 3 4
1 2 3 4 5
[1, 2, 3, 4, 5]
冒泡排序
依次比较相邻的两个数值的大小,根据具体的排序要求进行移位存放;
从小到大排序,将大数后移;
从大到小排序,将大数迁移;
比如要从小到大排序,那么就是第一个数和第二个数比,大的后移;再拿大的数和第三个数比,大数后移;依次比较,直到最大值到达最右侧位置,这是的第一轮比较结束。第二轮比较和第一轮一样,但是不会再去和最右侧的最大值进行比较,当第二轮比较结束后,这一轮的最大值显然要小于第一轮的最大值,所以将其放在此轮比较的最右侧(这是它的右侧有一个比它大的值)。这样依次比较,直至结束。
//冒泡排序
int[] arr = {1,5,2,6,8,3,9,4,7};
int temp = 0;
System.out.println("从小到大的排序:");
for (int i = 0; i < arr.length-1; i++) {
for (int j = 0; j < arr.length-i-1; j++) {
if(arr[j]>arr[j+1]){
temp = arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
运行结果为:
从小到大的排序:
1 2 3 4 5 6 7 8 9
Arrays工具类
包含了很多数组常用的方法。这些方法都是static修饰的。
- Boolean equals(type[] a,type[] b)
比较两个数组是否相等。
public static void main(String[] args){
int[] arr = {1,5,2,6,3,7,4,8};
int[] arr1 ={1,2,3,4,5,6,7,8};
int[] arr2 = {1,5,2,6,3,7,4,8};
boolean ea= Arrays.equals(arr, arr1);//比较两个数组是否相等
boolean ea1 = Arrays.equals(arr, arr2);//比较两个数组是否相等
System.out.println(ea);//false
System.out.println(ea1);//true
}
- String toString(type[] a)
将数组转换成字符串。
public static void main(String[] args){
int[] arr = {1,5,2,6,3,7,4,8};
String as = Arrays.toString(arr);//将数组转换为字符串
System.out.println(arr);//[I@15db9742
System.out.println(as);//[1, 5, 2, 6, 3, 7, 4, 8]
}
- void fill(type[] a,type value)
将数组的所有元素都赋值value。
public static void main(String[] args){
int[] arr = {1,5,2,6,3,7,4,8};
Arrays.fill(arr, 8);
System.out.println(Arrays.toString(arr));//[8, 8, 8, 8, 8, 8, 8, 8]
}
- void fill(type[] a,int fromIndex,int toIndex,type value)
对数组区间下标内的元素赋值value,包头不包尾。
public static void main(String[] args){
int[] arr = {1,5,2,6,3,7,4,8};
Arrays.fill(arr, 0, 2, 6);//对数组区间下标元素赋值(包头不包尾)
System.out.println(Arrays.toString(arr));//[6, 6, 2, 6, 3, 7, 4, 8]
}
- void sort(type[] a)
对数组元素进行排序。
public static void main(String[] args) {
int[] arr = {1,5,2,6,3,7,4,8};
Arrays.sort(arr);//使用工具类中的方法进行排序
System.out.println(Arrays.toString(arr));//[1, 2, 3, 4, 5, 6, 7, 8]
}
- void sort(type[] a, int fromIndex, int toIndex)
对数组指定下标区间的元素进行排序。
public static void main(String[] args) {
int[] arr = {1,5,2,6,3,7,4,8};
Arrays.sort(arr, 0, 3);//使用工具类中的方法进行区间排序
System.out.println(Arrays.toString(arr));//[1, 2, 5, 6, 3, 7, 4, 8]
}
常见面试题
打印输出一个数组
public static void main(String[] args) {
byte[] byteArray = {1,2,3,4,5};//byte类型数组
short[] shortArray = {1,2,3,4,5};//short类型数组
int[] intArray = {1,2,3,4,5};//int类型数组
long[] longArray = {1,2,3,4,5};//long类型数组
float[] floatArray = {1,2,3,4,5};//float类型数组
double[] doubleArray = {1,2,3,4,5};//double类型数组
String[] stringArray = {"1","2","3","4","5"};//Strig类型数组
// Arrays是一个工具类,java.util.Arrays,能够将byte、short、int、long、
// float、double、string类型的数组转换为string类型
String strB = Arrays.toString(byteArray);
String strS = Arrays.toString(shortArray);
String strI = Arrays.toString(intArray);
String strL = Arrays.toString(longArray);
String strF = Arrays.toString(floatArray);
String strD = Arrays.toString(doubleArray);
String strStr = Arrays.toString(stringArray);
System.out.println(intArray);//[I@15db9742
System.out.println(strB);//[1, 2, 3, 4, 5]
System.out.println(shortArray);//[S@6d06d69c
System.out.println(strS);//[1, 2, 3, 4, 5]
System.out.println(intArray);//[I@15db9742
System.out.println(strI);//[1, 2, 3, 4, 5]
System.out.println(longArray);//[J@7852e922
System.out.println(strL);//[1, 2, 3, 4, 5]
System.out.println(floatArray);//[F@4e25154f
System.out.println(strF);//[1.0, 2.0, 3.0, 4.0, 5.0]
System.out.println(doubleArray);//[D@70dea4e
System.out.println(strD);//[1.0, 2.0, 3.0, 4.0, 5.0]
System.out.println(stringArray);//[Ljava.lang.String;@5c647e05
System.out.println(strStr);//[1, 2, 3, 4, 5]
}
判断输出的顺序
//面试题1
public static void main(String[] args){
int i = 0;
for (i++; i++ < 10; i++) {
System.out.println(i+" ");//2 4 6 8 10
}
System.out.println(++i+" ");//13
//循环中的布尔表达式i++ < 10可以理解成i<10;i=i+1,先用i用完再加1
//第一次循环就是i声明的是0,for循环初始化(仅一次)后i=i+1=1,进行判断1<10,i= i+1=2,输出i是2,更新i=i+1=3
//第二次循环i是3,进行判断3<10,i=i+1=4,输出i是4,更新i=i+1=5。
//第三次循环i是5,进行判断5<10,i=i+1=6,输出i是6,更新i=i+1=7。
//第四次循环i是7,进行判断7<10,i=i+1=8,输出i是8,更新i=i+1=9。
//第五次循环i是9,进行判断9<10,i= i+1=10,输出i是10,更新i=i+1=11。
//第六次循环i是11,进行判断11>10,不满足循环的判断条件,i=i+1=12,不再输出i,不再更新i。
//循环结束,执行打印操作,此时i=12,++i=i+1=13。所以输出结果就是13。
}
//面试题2
static Boolean foo(char c){
System.out.print(c);//ABDCBDCB
return true;
}
public static void main(String[] args){
int i = 0;
for (foo('A');foo('B')&&(i<2);foo('C')) {
i++;
foo('D');
}
}
// for循环结构的基础:
// for(初始化表达式(只执行一次);布尔表达式;更新表达式){
// 循环体
// }
// 1、foo('A')就是初始化表达式;
// 2、foo('B')和(i<2)就是布尔表达式;
// 3、foo('C')就是更新表达式;
// 4、foo('D')就是循环体。
去重
list方式。需要判断数组的元素在不在list中存在。
set方式。set自带去重的功能。
public static void main(String[] args){
//方式一:通过list
int[] arr = {1,3,6,1,4,3,6,8,2,5,2,2};
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < arr.length; i++) {
if(!list.contains(arr[i])){
list.add(arr[i]);
}
}
System.out.println(list);//[1, 3, 6, 4, 8, 2, 5]
//方式二:通过set
int[] arr1 = {1,3,6,1,4,3,6,8,2,5,2,2};
Set<Integer> set = new HashSet<Integer>();
for (int i = 0; i < arr1.length; i++) {
set.add(arr1[i]);
}
System.out.println(set);//[1, 2, 3, 4, 5, 6, 8]
}
数组中的最大值最小值
- 冒泡排序方式,先排出顺序,再找最大值最小值。
public static void main(String[] args){
int[] arr = {1,4,7,2,5,6,8,3};//正常数组
int temp;
for (int i = 0; i < arr.length-1; i++) {
for (int j = 0; j < arr.length-i-1; j++) {
if (arr[j] > arr[j+1]) {//从左往右由小到大排序
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
System.out.println(Arrays.toString(arr));//[1, 2, 3, 4, 5, 6, 7, 8]
System.out.println(arr[arr.length-1]);//最大值是8
System.out.println(arr[0]);//最小值是1
}
public static void main(String[] args){
int[] arr1 = {1,3,6,1,4,3,6,8,2,5,2,2};//存在重复值的数组
int temp1;
for (int i = 0; i < arr1.length-1; i++) {
for (int j = 0; j < arr1.length-i-1; j++) {
if (arr1[j] > arr1[j+1]) {//从左往右由小到大排序
temp1 = arr1[j];
arr1[j] = arr1[j+1];
arr1[j+1] = temp1;
}
}
}
System.out.println(Arrays.toString(arr1));//[1, 1, 2, 2, 2, 3, 3, 4, 5, 6, 6, 8]
System.out.println(arr1[arr1.length-1]);//最大值是8
System.out.println(arr1[0]);//最小值是1
}
- 假设法方式,假设第一个是最大的,拿它去跟别的比。
public static void main(String[] args){
int[] arr2 = {1,4,7,2,5,6,8,3};
int max = arr2[0];//求最大值时,假设第一个最大
int idx = 0;//最大值对应的元素下标
for (int i = 0; i < arr2.length; i++) {
if (arr2[i]>max) {
max = arr2[i];
idx = i;
}
}
System.out.println(max);//8
System.out.println(idx);//6
int min = arr2[0];//求最小值时,假设第一个最小
int idx2 = 0;//最小值对应的元素下标
for (int i = 0; i < arr2.length; i++) {
if (arr2[i]<min) {
min = arr[i];
idx2 = i;
}
}
System.out.println(min);//1
System.out.println(idx2);//0
}
删除数组中的元素
//删除数组中的元素
public static void main(String[] args) {
String[] arr = {"1","2","3","4"};
System.out.println(Arrays.toString(arr));//[1, 2, 3, 4]
//Arrays.asList(arr)产生的list所持有的add、remove方法执行时会报错,因为这个Arrays.asList()方法返回的
//是Arrays的内部类ArrayList,并不是我们通常使用的java.util.ArrayList,其实Arrays的arrayList
//和java.util.ArrayList都继承了AbstractList,add、remove等方法在AbstractList中默认是
//throw UnsupportedOperationException,并且不会做任何操作,java.util.ArrayList中重写了这些方法,
//但是Arrays中的内部类ArrayList并没有重写这些方法。
//方式一:使用Arrays工具类的asList()方法
List<String> asList = Arrays.asList(arr);
List<String> arrList = new ArrayList<String>(asList);
arrList.remove(2);//根据下标删除
arrList.remove("2");//根据元素删除
System.out.println(arrList);//[1, 4]
String[] arr1 = arrList.toArray(new String[1]);//将list转换为数组
System.out.println(Arrays.toString(arr1));//[1, 4]
//删除数组中的元素
public static void main(String[] args) {
String[] arr = {"1","2","3","4"};
System.out.println(Arrays.toString(arr));//[1, 2, 3, 4]
//Arrays.asList(arr)产生的list所持有的add、remove方法执行时会报错,因为这个Arrays.asList()方法返回的
//是Arrays的内部类ArrayList,并不是我们通常使用的java.util.ArrayList,其实Arrays的arrayList
//和java.util.ArrayList都继承了AbstractList,add、remove等方法在AbstractList中默认是
//throw UnsupportedOperationException,并且不会做任何操作,java.util.ArrayList中重写了这些方法,
//但是Arrays中的内部类ArrayList并没有重写这些方法。
//方式二:
List<String> strList = new ArrayList<String>();
for (int i = 0; i < arr.length; i++) {
strList.add(arr[i]);
}
strList.remove(1);//根据下标删除
strList.remove("4");//根据元素删除
System.out.println(strList);//[1, 3]
String[] arr2 = strList.toArray(new String[1]);//list转数组
System.out.println(Arrays.toString(arr2));//[1, 3]
//删除数组中的元素
public static void main(String[] args) {
String[] arr = {"1","2","3","4"};
System.out.println(Arrays.toString(arr));//[1, 2, 3, 4]
//方式三:
//把最后一个元素替代指定的元素,然后数组缩容。
Scanner sc = new Scanner(System.in);
System.out.println("请输入要删除第几个元素:");
int n = sc.nextInt();
sc.close();
//把最后一个元素替代指定的元素
arr[n-1] = arr[arr.length-1];
//数组缩容
arr = Arrays.copyOf(arr, arr.length-1);
System.out.println(Arrays.toString(arr));
}
运行结果:
[1, 2, 3, 4]
请输入要删除第几个元素:
2 //(需要在这里键盘输入要删除那个元素,输入后点击enter键)
[1, 4, 3]