一.数组概述
数组是存储同一种数据类型,多个元素的容器。
数组即可存储基本数据类型,也可以存储引用数据类型。
image.png
数组的定义格式:
- 格式1:数据类型[] 数组名;
- 格式2:数据类型 数组名[];
1)注意:这两种定义做完了,数组中是没有元素值的。如何对数组的元素进行初始化呢?
二.数组初始化
Java中的数组必须先初始化,然后才能使用。
数组初始化就是为数组中的数组元素分配内存空间,并为每个数组元素赋值。
数组的初始化有以下两种方式:
动态初始化:初始化时程序员只指定数组长度,由系统为数组元素分配初始值。
int[] arr = new int[3];
arr[0]=2;
arr[1]=5;
arr[2]=7;
静态初始化:初始化时由程序员显式指定每个数组元素的初始值,由系统决定数组长度。
//完整写法
int[] arr = new int[]{2,5,7};
//其他写法 不推荐
//解释:定义了一个int类型的数组,这个数组中可以存放3个int类型的值。结果相同,但推荐用第一种写法。
//一般将实例名(这里指arr)放在等号左侧相邻的位置,否则容易引起歧义(变量名到底是 arr 还是 arr[] ?)。
int arr[] = new int[]{2,5,7};
//简化写法 不推荐
int[] arr = {2,5,7};
2.1 动态初始化
动态初始化是给出数组的长度,初始值由系统为数组分配。
格式:
- 标准写法:数据类型[] 数组名 = new 数据类型[数组长度];
- 其他写法:数据类型 数组名[] = new 数据类型[数组长度];(不推荐)
实例:
-- 定义了一个int类型的数组,这个数组中可以存放3个int类型的值,系统自定分配初始值,int类型初始值为0。
int[] arr = new int[3];
int arr[] = new int[3]; //不推荐
数组长度:
上例中数组的长度为3
获取元素的格式:
- 数组名[索引] => arr[0] = 0;
- 索引编号从0开始,最大的编号是数组的长度 -1 => new int[3] 索引最大编号为 2;
动态初始化的值:
动态初始化数据类型 | 默认值 | 备注 |
---|---|---|
byte,short,int,long | 0 | |
float double | 0.0 | |
char | ‘\u0000’ | \u表示unicode编码,\u0000 表示Unicode编码中的 null |
boolean | false | |
引用类型 | null |
代码:
package Java_study;
public class shuzu1 {
public static void main(String[] args) {
//数据类型[] 数组名 = new 数据类型[数组长度];
int[] arr = new int[3];
/*
* 左边:
* int:说明数组中的元素的数据类型是int类型
* []:说明这是一个数组
* arr:是数组的名称
* 右边:
* new:为数组分配内存空间
* int:说明数组中的元素的数据类型是int类型
* []:说明这是一个数组
* 3:数组的长度,其实就是数组中的元素个数
*/
//数据类型[] 数组名 = new 数据类型[数组长度];
int[] arr2 = new int[4];
//遍历arr数组,并给数组总的每个元素赋值(除最后一个)
for (int i = 0; i < arr2.length -1; i++) {
arr2[i] = i * 5 - 1;
}
/*
* 左边:
* int:说明数组中的元素的数据类型是int类型
* []:说明这是一个数组
* arr:是数组的名称
* 右边:
* new:为数组分配内存空间
* int:说明数组中的元素的数据类型是int类型
* []:说明这是一个数组
* 3:数组的长度,其实就是数组中的元素个数
*/
//输出数组名
System.out.println("arr2:" + arr2);
System.out.println("arr2[0]:" + arr2[0]);
System.out.println("arr2[1]:" + arr2[1]);
System.out.println("arr2[2]:" + arr2[2]);
System.out.println("arr2[3]:" + arr2[3]);
}
}
测试记录:
arr2:[I@15db9742
arr2[0]:-1
arr2[1]:4
arr2[2]:9
arr2[3]:0
2.2 数组内存结构
Java 程序在运行时,需要在内存中的分配空间。为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
- 栈:存储局部变量,对象实例的地址
- 堆:存储new出来的东西,对象实例
- 方法区:包含类从磁盘到内存的整个生命周期,编译>加载>连接>初始化>使用>卸载
- 本地方法区:和系统相关,实现Java应用与Java外面环境的交互,本地方法提供接口,实现体在外面其他语言。在windows中就是使用windows系统语言实现Java代码
数组的内存图:
需要掌握一个数组在内存中的变化,其他的内存图能看懂即可。
数组与对象的处理方式相同,因此通过一个实例:调用方法m1时的过程,来观察数组及其引用的存储位置。
class A {
int x;
int y;
}
...
public void m1() {
int i = 0;
m2();
}
public void m2() {
A a = new A();
}
- 当m1被调用的时候,栈帧Frame-1被创建并push到栈中,同时局部变量i也在栈帧Frame-1内创建。
- 然后,m2方法在m1方法内部被调用,栈帧Frame-2被创建并push到栈中,在m2方法中,一个新的对象A在堆中被创建,而它的引用则被put到栈帧Frame-2里;
2.3 静态初始化
数组的静态初始化:给出初始化值,由系统决定长度。
格式:
- 标准写法:数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3,...};
- 其他写法:数据类型 数组名[] = new 数据类型[]{元素1,元素2,元素3,...};(不推荐)
- 简化写法:数据类型[] 数组名 = {元素1,元素2,元素3,...}; (不推荐)
实例:
int[] arr = new int[]{2,5,7};
int arr[] = new int[]{2,5,7}; //不推荐
int[] arr = {2,5,7}; //不推荐
数组长度:
数组中元素的个数。3个。
获取元素的格式:
数组名[索引] => arr[0] = 2;
索引编号从0开始,最大的编号是数组的长度 -1 => new int[3] 索引最大编号为 2
代码:
package Java_study;
public class shuzu2 {
public static void main(String[] args) {
//静态初始化一个数组
int[] arr = {1, 2, 3};
//在栈中存储了arr实例名对应在 堆中的(实例对象)内存地址 arr:[I@50134894
System.out.println("arr:" + arr);
//在堆中存储了arr实例对象索引为0的 实际值1
System.out.println("arr[0]:" + arr[0]);
//在堆中存储了arr实例对象索引为1的 实际值2
System.out.println("arr[1]:" + arr[1]);
//在堆中存储了arr实例对象索引为2的 实际值3
System.out.println("arr[2]:" + arr[2]);
}
}
测试记录:
arr:[I@15db9742
arr[0]:1
arr[1]:2
arr[2]:3
2.4 二维数组
二维数组是元素为一维数组的数组。
格式:
- 动态初始化: m 表示的是二维数组中一维数组的个数;n 表示的是一维数组中的元素个数
1)标准写法:数据类型[m][n] 数组名 = new 数据类型[m][n];
2)其他写法:数据类型[m] 数组名[n] = new 数据类型[m][n]; (不推荐)
3)其他写法:数据类型 数组名[m][n] = new 数据类型[m][n]; (不推荐) - 静态初始化
1)标准写法:数据类型[][] 数组名 = new 数据类型[][]{{元素...},{元素...},{元素...},...};
2)简化格式:数据类型[][] 数组名 = {{元素...},{元素...},{元素...},...};
动态初始化实例:
解释:在Java中我们只能有一个一维数组。2维数组只是1维数组的数组。
动态初始化一个数组长度为3的二维数组,二维数组中的元素为3个长度分别为3,5,4的动态初始化的一维数组。
int[ ][ ] arr = new int[3][ ];
//int[ ] arr[ ] = new int[3][ ];//不推荐
//int arr[ ][ ] = new int[3][ ];//不推荐
arr[0] = new int[3];
arr[1] = new int[5];
arr[2] = new int[4];
arr[0][0] = 1;
arr[0][1] = 2;
arr[0][2] = 3;
图解动态初始化实例:
image.png
静态初始化实例:
int[][] arr = new int[][]{{1, 2, 3}, {10, 20, 30}, {100, 200}, {Integer.valueOf('s'), Integer.valueOf('a')}};
//int[][] arr = {{1, 2, 3}, {10, 20, 30}, {100, 200}, {Integer.valueOf('s'), Integer.valueOf('a')}};//不推荐
数组长度:
数组中元素的个数。外层为3个,内层分别为3个,5个,4个。
获取元素的格式:
数组名[索引] => arr[0][0] = 0;
索引编号从0开始,最大的编号是数组的长度 -1 => new int[3] 索引最大编号为 2
代码:
package Java_study;
public class shuzu3 {
public static void main(String[] args) {
//今天初始化一个二维数组,其中包含4个以为数组
int[][] arr = new int[][] {
{1, 2, 3},
{10, 20 ,30},
{100, 200},
{Integer.valueOf('s'), Integer.valueOf('a')}
};
System.out.println("arr[0]:" + arr[0]);
System.out.println("arr[1]:" + arr[1]);
System.out.println("arr[2]:" + arr[2]);
System.out.println("==========");
System.out.println("arr[0][0]: " + arr[0][0]);
System.out.println("arr[0][1]: " + arr[0][1]);
System.out.println("arr[0][2]: " + arr[0][2]);
System.out.println("arr[2][0]: " + arr[2][0]);
System.out.println("arr[2][1]: " + arr[2][1]);
System.out.println("arr[3][0]: " + arr[3][0]);
System.out.println("arr[3][1]: " + arr[3][1]);
//如数组索引不存在会报错
try {
System.out.println("arr[2][2]: " + arr[2][2]);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组越界异常: 访问不存在的索引.");
// e.printStackTrace();
}
//遍历数组: 首先遍历外层,获取二维数组中的每一个元素
for (int i = 0; i < arr.length; i++) {
//arrInner为外层数组的元素,这个元素为一维数组
int[] arrInner = arr[i];
//继续遍历这个以为数组arrInner
for (int j = 0; j < arrInner.length; j++) {
//取出一维数组中的每一个int类型元素,并赋值给变量a,并打印这个元素值
int a = arrInner[j];
System.out.println(a);
/*
1
2
3
-----
10
20
30
-----
100
200
-----
115 ('s')对应码表值为115
97 ('a')对应码表值为97
-----
*/
}
System.out.println("-----");
}
}
}
测试记录:
arr[0]:[I@15db9742
arr[1]:[I@6d06d69c
arr[2]:[I@7852e922
==========
arr[0][0]: 1
arr[0][1]: 2
arr[0][2]: 3
arr[2][0]: 100
arr[2][1]: 200
arr[3][0]: 115
arr[3][1]: 97
数组越界异常: 访问不存在的索引.
1
2
3
-----
10
20
30
-----
100
200
-----
115
97
-----
三.数组的方法
- 声明一个数组
String[] aArray = new String[5];
String[] bArray = {"a","b","c", "d", "e"};
String[] cArray = new String[]{"a","b","c","d","e"};
- 打印一个数组
int[] intArray = { 1, 2, 3, 4, 5 };
String intArrayString = Arrays.toString(intArray);
// print directly will print reference value
System.out.println(intArray);
// [I@7150bd4d
System.out.println(intArrayString);
// [1, 2, 3, 4, 5]
- 根据数组创建ArrayList
String[] stringArray = { "a", "b", "c", "d", "e" };
ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(stringArray));
System.out.println(arrayList);
// [a, b, c, d, e]
- 判断数组内部是否包含某个值
String[] stringArray = { "a", "b", "c", "d", "e" };
boolean b = Arrays.asList(stringArray).contains("a");
System.out.println(b);
// true
- 连接两个数组
int[] intArray = { 1, 2, 3, 4, 5 };
int[] intArray2 = { 6, 7, 8, 9, 10 };
// Apache Commons Lang library
int[] combinedIntArray = ArrayUtils.addAll(intArray, intArray2);
- 声明一个内联数组(array inline)
method(new String[]{"a", "b", "c", "d", "e"});
- 根据分隔符拼接数组元素(去掉最后一个分隔符)
// containing the provided list of elements
// Apache common lang
String j = StringUtils.join(new String[] { "a", "b", "c" }, ", ");
System.out.println(j);
// a, b, c
- ArrayList转数组
String[] stringArray = { "a", "b", "c", "d", "e" };
ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(stringArray));
String[] stringArr = new String[arrayList.size()];
arrayList.toArray(stringArr);
for (String s : stringArr)
System.out.println(s);
- Array转Set
Set<String> set = new HashSet<String>(Arrays.asList(stringArray));
System.out.println(set);
//[d, e, b, c, a]
- 反转数组
int[] intArray = { 1, 2, 3, 4, 5 };
ArrayUtils.reverse(intArray);
System.out.println(Arrays.toString(intArray));
//[5, 4, 3, 2, 1]
- 删除数组元素
int[] intArray = { 1, 2, 3, 4, 5 };
int[] removed = ArrayUtils.removeElement(intArray, 3);//create a new array
System.out.println(Arrays.toString(removed));
- 整形转字节数组
byte[] bytes = ByteBuffer.allocate(4).putInt(8).array();
for (byte t : bytes) {
System.out.format("0x%x ", t);
}
网友评论