Java中的数组——详解!
一、数组的概念与基本要素
1.概念
数组(array)是一种最简单的复合数据类型,它是有序数据的集合,数组中的每个元素具有相同的数据类型,可以用一个统一的数组名和不同的下标来确定数组中唯一的元素。根据数组的维度,可以将其分为一维数组、二维数组和多维数组等。
2.基本要素
一个数组由4个基本元素构成:数组名称、数组元素、元素索引、数据类型。
数组的索引就相当于C语言中数组的下标,关于数组的长度可以用数组名.length求出。
int[] array = {1,2,3};
int sz = arr.length;
- 1
- 2
3.数组的定义
关于数组的定义,其实有很多种定义方法,接下来,我会给你们介绍几种定义数组的方法。
//第一种定义数组的方法:
int[] array1 = {1,2,3};//直接赋值(静态初始化)
//int[]是数组的类型,array为数组名,随意取名字
//第二种定义数组的方法:
int[] array2 = new int[]{1,2,3,4};//数组的动态初始化
//第三种定义数组的方法:
int[] array3 = new int[10];//只是分配了内存,但是没有进行赋值,默认值都是0,
//第四种定义数组的方法:
int[] array4;
array = new int[]{1,2,3};//一定要为数组符初值,不然编译器会报错,
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
对于没有赋初值的数组,编译器会自动赋值,以下表格是不同类型的数组,初值大小:
类型 | 初始值 |
---|---|
byte | 0 |
short | 0 |
int | 0 |
long | 0 |
float | 0.0f |
double | 0.0 |
char | ‘/u0000’ |
boolean | false |
4.注意事项
- 静态初始化虽然没有指定数组的长度,编译器在编译时会根据{}中元素个数来确定数组的长度。
- 静态初始化时, {}中数据类型必须与[]前数据类型一致。
- 静态初始化可以简写,省去后面的new T[]。T可以为任意数据类型。
- 如果数组中存储元素类型为引用类型,默认值为null。
二、数组的使用
1.对数组中的元素进行访问
数组在内存中是一段连续的空间,空间的编号都是从0开始的,依次递增,该编号称为数组的下标,数组可以通过
索引访问其任意位置的元素。
int[] array = {1,2,3,4,5,6,7,8};
System.out.println(array[0]);//1
System.out.println(array[1]);//2
System.out.println(array[2]);//3
System.out.println(array[3]);//4
System.out.println(array[4]);//5
//当然也可以对数组中的元素进行修改,、
array[0]=111;
System.out.println(array[0]);//111
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
2.注意事项
(1)数组是一段连续的内存空间,因此支持随机访问,即通过下标访问快速访问数组中任意位置的元素。
(2)下标从0开始,介于[0, N)之间不包含N,N为元素个数,不能越界,否则会报出下标越界异常。
所以在访问数组元素时一定不要越界!!!
3.对数组的遍历
对于什么是对数组的遍历,就是将数组的元素全都访问一遍,如将数组中的全部元素的打印一遍。
第一种数组遍历方法:直接打印数组中的每一个元素
Demo:
int[] array = {1,2,3,4};
System.out.println(array[0]);
System.out.println(array[1]);
System.out.println(array[2]);
System.out.println(array[3]);
- 1
- 2
- 3
- 4
- 5
本方法对于元素个数较少的数组来说可以应用,但对于有几十个元素的数组来说,太麻烦了,接下来为大家讲解第二种方法。
第二种数组遍历的方法:采用for循环打印
Demo:
int[] array = {1,2,3,4};
for(int i = 0;i < array.length;i++) {
System.out.print(array[i]);
}
- 1
- 2
- 3
- 4
第三种数组遍历的方法:采用foreach的方式
Demo:
int[] array = {1,2,3,4,5};
for(int x : array) {
System.out.print(x+" ");
}
- 1
- 2
- 3
- 4
foreach的语法格式:冒号右边写数组名,左边写由数组当中数据类型定义的变量。
但是foreach也有局限性,如果要求去访问数组中的某一个元素的时候,就不能进行访问,显然这时的for循环就占据了优势。
第四种遍历数组的方法:采用专门的工具
Demo:
import java.util.Arrays;
int[] array = {1,2,3,4,5};
String ret = Arrays.toString(array);//将数组转换成字符串,然后返回.
System.out.println(ret);
- 1
- 2
- 3
- 4
- 5
注:要使用Arrays这个工具时要导入其专有的包!
三、数组在内存的存在形式
1.数组是一种引用变量
基本数据类型创建的变量,称为基本变量,该变量空间中直接存放的是其所对应的值;
而引用数据类型创建的变量,一般称为对象的引用,其空间中存储的是对象所在空间的地址,数组就是一种引用数据类型。
int a = 10;
int b = 20;
int[] array =new int[]{1,2,3,4};
- 1
- 2
- 3
在上述代码中,a、b、arr,都是方法内部的变量,因此其空间都在main方法对应的栈帧中分配。
a、b是内置类型的变量,因此其空间中保存的就是给该变量初始化的值。
array是数组类型的引用变量,其内部保存的内容可以简单理解成是数组在堆空间中的首地址。
从图中可以看出,引用变量与基本数据类型的变量的不同,引用变量不会存储对象本身,可以简单理解成存储的是对象在堆中空间的起始地址。通过该地址,引用变量便可以去操作对象,(但其实这“地址”是经过哈希得到的),此前不要求掌握该知识点。
2了解引用变量(数组)
Demo:
int[] array1 = {1,2,3,4};
System.out.print(Arrays.toString(array1));//打印[1,2,3,4]
int[] array2 = array1;
array2[1] = 99;
System.out.print(Arrays.toString(array1));//打印[1,99,3,4]
System.out.print(Arrays.toString(array2));//打印[1,99,3,4]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
代码的解析:
首先创建一个数组array1,并初始化赋值为1,2,3,4,然后打印数组array1,接着申请另一款空间,用来创建array2,且array2=array1,说明两个数组都指向同一块空间,修改array2中的第二个元素也就相当于修改了array1中对应的元素。
3.注意事项
(1)一个引用不能同时指向多个对象
例:
(2)一个对象可以被多个引用所指向
例:
(3)
int[] array = 0;
/*这种写法是错误的,因为0是一种基本数据类型,
*而array是一种引用数据类型,如果将0改成null就不会错。
*即代表这个引用不指向任何对象
*/
- 1
- 2
- 3
- 4
- 5
注:null在Java中表示空引用,也就是一个不指向对象的引用,并不是0的意思。
四、数组的应用场景
1.用来保存数据
Demo:
int[] array = {1,2,3};
for(int i = 0;i < array.length;i++ ) {
System.out.print(array[i]);
}
- 1
- 2
- 3
- 4
2.数组作为方法的参数
Demo:
public class TestDemo {
public static void func1 (int[] array1) {
array = new int[10];
}
public static void func2 (int[] array) {
array[0] = 99;
}
public static void main(String[] args) {
int[] array = {1,2,3,4};
func1(array);
System.out.println(Arrays.toString(array));
func2(array);
System.out.println(Arrays.toString(array));
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
代码解释:对func1方法进行解释就行,func2同理
形参的指向改变不会影响实参的指向改变!!!
3.数组作为方法的返回值
Demo:
public class TestDemo {
public static int[] func() {
int[] array = {1,2,3,4};
return array;
}
public static void main(String[] args) {
int[] ret = func();
System.out.println(Arrays.toString(ret));
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
五、数组的练习
小伙伴们,也可以直接去写一下,再过来看示例代码,增强自己的代码能力。
1.数组转成字符串
Demo:
//第一种是利用编译器自带的工具
int[] array = {1,2,3};
String ret = Arrays.toString(array);
System.out,print(ret);
//第二种利用自己写的方法去解决
public class TestDemo {
public static String mytoString(int[] arr) {
if(arr == null){
return "null";
}
String ret = "[";
for(int i=0;i<arr.length;i++) {
ret+=arr[i];
if(i!=arr.length-1) {
ret+=",";
}
}
ret+="]";
return ret;
}
public static void main(String[] args) {
int[] array = {1,2,3,4,5,6};
String ret = mytoString(array);
System.out.println(ret);
}
//打印结果为 [1,2,3,4,5,6]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
2.数组的拷贝
本练习还是采用两种方式,一种是编译器自带的,另一种是自己所写的方法。
下面是错误代码!!!
/*
int[] array1 = {1,2,3};
int[] array2 = array1;
*/
//这不是对数组的拷贝,因为没有产生新的空间
- 1
- 2
- 3
- 4
- 5
Demo:
//第一种:自己写的方法
public class TestDemo {
public static void main(String[] args) {
int[] array1 = {1,2,3,4};
int[] array2 = new int[array1.length];
for(int i=0;i<array1.length;i++) {
array2[i]=array1[i];
}
System.out.println(Arrays.toString(array1));
System.out.println("复制之后的数组为:");
System.out.println(Arrays.toString(array2));
}
}
//最后输出为:
[1,2,3,4]
复制之后的数组为:
[1,2,3,4]
//第二种编译器自带的方法
import java.util.Arrays;
int[] array1 = {1,2,3,4};
int[] array2 = Arrays.copyOf(array1,array1.length);
System.out.println(Arrays.toString(array1));
System.out.println(Arrays.toString(array2));
//最后输出为:
[1,2,3,4]
[1,2,3,4]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
显然自己写的方法没有编译器自带的工具简洁,但是不能说有了这些工具就可以不用写代码了,自己的能力还是要加强,这些工具只是帮我们减轻了负担,但是原理还是要自己弄懂。
3.求数组的平均值
由于这道题比较简单,本博主直接就给答案咯。
Demo:
public class TestDemo {
public static void main(String[] args) {
int[] array = {23,45,2,74,86,24};
int sum = 0 ;
double ave = 0.0f;
for(int i=0; i<array.length;i++) {
sum=sum + array[i];
}
ave = sum/array.length;
System.out.println(ave);
}
}
//最后结果:
42.0
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
4.数组排序(冒泡排序)
算法思路:
- 将数组中相邻元素从前往后依次进行比较,如果前一个元素比后一个元素大,则交换,一趟下来后最大元素
就在数组的末尾 - 依次从上上述过程,直到数组中所有的元素都排列好
Demo:
public class TestDemo {
public static void main(String[] args) {
int[] array = {23,4,53,1,765,52,356,9,7,2,324};
System.out.println("排序之前的数组:");
System.out.println(Arrays.toString(array));
for(int j = 1;j<array.length;j++) {
for(int i = 0;i<array.length-j;i++) {
if(array[i]>array[i+1]) {
int tmp = array[i]; //交换数据
array[i] = array[i+1];
array[i+1] = tmp;
}
}
}
System.out.println("排序之后的数组:");
System.out.println(Arrays.toString(array));
}
}
//排序之前的数组:
[23, 4, 53, 1, 765, 52, 356, 9, 7, 2, 324]
//排序之后的数组:
[1, 2, 4, 7, 9, 23, 52, 53, 324, 356, 765]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
5.数组逆序
题目理解:就是给定一个数组,将其倒序输出。
思路:
先定义两个下标分别指向数组的第一个元素和最后一个元素,将数组中的第一个元素和最后一个元素交换位置,然后指向第一个元素的下标进行加加,指向最后一个元素的下标进行减减。
Demo:
public class TestDemo {
public static void main(String[] args) {
int[] array = {1,2,3,4,5,6};
int left = 0;
int right = array.length-1;
System.out.println("排序之前的数组:");
System.out.println(Arrays.toString(array));
while(left<=right) {
int tmp = array[left];
array[left] = array[right];
array[right] = tmp;
left++;
right--;
}
System.out.println("排序之后的数组:");
System.out.println(Arrays.toString(array));
}
}
//运行结果:
排序之前的数组:
[1, 2, 3, 4, 5, 6]
排序之后的数组:
[6, 5, 4, 3, 2, 1]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
六、二维数组
1.二维数组的定义
关于二维数组的定义有很多种方法,这里咱们介绍最常用的三种。
Demo:
//第一种定义二维数组的方法:(行数和列数都知道的情况)
// 数组类型[][] 数组名 = new 数组类型[行数][列数];
int[][] arr = new int[2][3];//定义一个3行4列的数组
- 1
- 2
- 3
- 4
//第二种定义数组的方法:(只知道行数,不知道列数)
// 数组类型[][] 数组名 = new 数组类型[行数][];
int[][] arr = new int[2][];
- 1
- 2
- 3
- 4
//第三种定义二维数组的方法:(知道具体的数据)
// 数据类型[][] 数组名 = {{第0行初始值},{第1行初始值},···,{第n行初始值}};
int[][] arr = {{1,2},{3,4,5},{6,7,8,9}};
- 1
- 2
- 3
- 4
以上就是关于二维数组最常见的定义方法!!!
2.二维数组的打印
二维数组本质上也就是一维数组, 只不过每个元素又是一个一维数组.
Demo:
public class TestDemo {
public static void main(String[] args) {
int[][] array = {{1,2},{3,4,5},{6,7,8,9}};
for(int i=0;i< array.length;i++) {
for(int j=0;j<array[i].length;j++) {
System.out.print(array[i][j]+" ");
}
System.out.println(" ");
}
}
}
//运行结果:
1 2
3 4 5
6 7 8 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
由于二维数组的应用和一维数组并没有太大的区别,所以,在这里不做介绍,学会如何定义二维数组就好。
评论记录:
回复评论: