Java中的数组
一、 什么是数组
数组就是相同数据类型的集合。
是有序的元素序列。 若将有限个类型相同的变量的集合命名,那么这个名称为数组名。组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量。用于区分数组的各个元素的数字编号称为下标。数组是在程序设计中,为了处理方便, 把具有相同类型的若干元素按无序的形式组织起来的一种形式。 这些无序排列的同类数据元素的集合称为数组。
二、一维数组
定义: 一维数组是由数字组成的以单纯的排序结构排列的结构单一的数组。一维数组是计算机程序中最基本的数组。
数组的初始化:
一维数组的初始化包含以下几种
- 数组类型 [ ] 数组名={初始化数据};
- 数组类型 [ ] 数组名= new {数据类型 {初始化数据};
- 数组类型 [ ] 数组名= new 数据类型 [数组长度];
代码示例:
int[] arr1= {1,2,3,4};
int[] arr2=new int[]{1,2,3,4};
int[] arr3=new int[4];
注意:
new:产生一个对象。(数组本身就是一个对象)。
引用:用来尊饭对象的地址。(如上面的arr)。
数组定义后未初始化时,默认值时0;如果数组中时引用类型则默认值为 null。
数组下标越界异常:
java.lang.Array indexOutOfBoundsException
数组的遍历:
数组名.length: 作用是求数组长度(length不是方法,而是数组的属性)
for 循环遍历数组:
int[] arr = {1, 2, 3};
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
// 执行结果
1 2 3
for-each 遍历数组:
for(变量:数组名)
for-each 是 for 循环的另外一种使用方式. 能够更方便的完成对数组的遍历. 可以避免循环条件和更新语句写错。
int[] arr = {1, 2, 3};
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]+" ");
}
// 执行结果
1 2 3
Arrays.toString(数组名):
import java.util.Arrays //Arrays的导入
int[] arr = {1,2,3,4,5,6};
String newArr = Arrays.toString(arr);
System.out.println(newArr);
// 执行结果
[1, 2, 3, 4, 5, 6]
数组的拷贝:
数组拷贝的几种方法:
- System.arraycopy()
- Arrays.copyof()
- arraycopy()
- 数组名.clone()
数组拷贝时分为浅拷贝和深拷贝
深拷贝:数组中存放的是简单类型,对拷贝后的数组修改不影响原数组。
浅拷贝:数组中存放的是引用类型,如果是两个引用同时执行一个对象,那么通过一个引用修改一个对象时另一个引用也会受到影响。
在数组的使用时我们经常用到Arrays方法
Arrays的导入包:import.java.util.Arrays(快捷键:alt+enter)。
这里我们需要注意System.arraycopy()和Arrays.copyof()的区别。
System.arraycopy():是被native修饰的方法。
Arrays.copyof():方法内部调用了System.arraycopy()。
数组元素查找:
数组元素查找即在数组查找所有查找的元素,并返回该元素下标。
简单的查找方法有两种:顺序查找和二分查找
顺序查找:
public static int find(int[] arr, int toFind) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == toFind) {
return i;
}
}
return -1; // 表示没有找到
}
二分查找:
public static int binarySearch(int[] arr,int key) {
int left =0;
int right = arr.length-1;
int mid=0;
while(left<=right) {
mid = (left+right)/2;
if(key<arr[mid]) {
right=mid-1;
} else if(key>arr[mid]) {
left=mid+1;
} else {
return mid;
}
}
return -1;
}
JVM的内存区域划分:
- 程序计数器 (PC Register): 只是一个很小的空间, 保存下一条执行的指令的地址. 虚拟机栈(JVM Stack): 重点是存储局部变量表(当然也有其他信息). 我们刚才创建的 int[] arr 这样的存储地址 的引用就是在这里保存.
- 本地方法栈(Native Method Stack): 本地方法栈与虚拟机栈的作用类似. 只不过保存的内容是Native方法的局部 变量. 在有些版本的 JVM 实现中(例如HotSpot), 本地方法栈和虚拟机栈是一起的.
native方法:底层由c/c++实现,运行快. - 堆(Heap): JVM所管理的最大内存区域. 使用 new 创建的对象都是在堆上保存 (例如前面的 new int[]{1, 2, 3} )
- 方法区(Method Area): 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据. 方法编译出的的字节码就是保存在这个区域.
- 运行时常量池(Runtime Constant Pool): 是方法区的一部分, 存放字面量与符号引用
注意:
局部变量和引用保存在栈上, new 出的对象保存在堆上.
堆的空间非常大, 栈的空间比较小.
堆是整个 JVM 共享一个, 而栈每个线程具有一份(一个 Java 程序中可能存在多个栈)
三、维数组:
规则的数组定义:
- 数据类型 [ ] 数组名称 = new 数据类型 [行数][列数] { 初始化数据 };
- 数据类型 [ ] 数组名称 = new 数据类型 [行数][ ] { 初始化数据 };
int[] arr=new int[2][2]{{1,2},{3,4}};
int[] arr=new int[2][];
不规则的数组定义:
- 数据类型 [ ] 数组名称 = new 数据类型 [ ][ ] { 初始化数据 };
int[] arr=new int[][]{{2},{3,4}};
打印二维数组:
for (int row = 0; row < arr.length; row++) {
for (int col = 0; col < arr[row].length; col++) {
System.out.printf("%d\t", arr[row][col]);
}
System.out.println(" ");
}
这种方法规则和不规则二维数组的打印都可以使用。
for (int row = 0; row < arr.length; row++) {
for (int col = 0; col < arr[0].length; col++) {
System.out.printf("%d\t", arr[row][col]);
}
System.out.println("");
}
这种方法只适用于规则的二维数组打印。
上一篇: LintCode 题目:三数之中的最大值
下一篇: Java中的数组