Java中数组的使用
Posted Unstoppedable
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中数组的使用相关的知识,希望对你有一定的参考价值。
Java中数组的使用
1.数组的基本用法
1.1一维数组的使用
1.1.1一维数组的声明和初始化
一维数组的声明
声明方式:
type var[] 或 type[] var;
例如:
int a[];
int[] a1;
double b[];
String[] c; //引用类型变量数组
Java语言中声明数组时不能指定其长度(数组中元素的数)
例如:
int a[5]; //非法
一维数组的初始化
动态初始化:
数组声明且为数组元素分配空间与赋值的操作分开进行
例如:
int[] arr = new int[3];
arr[0] = 6;
arr[1] = 1;
arr[2] = 1;
String names[];
names = new String[3];
names[0] = "钱学森";
names[1] = "邓稼先";
names[2] = "袁隆平";
静态初始化:
在定义数组的同时就为数组元素分配空间并赋值
例如:
int arr[] = new int[]{ 6, 1, 1};
//或者
int[] arr = {1,1,6};
String names[] = {"李四光","茅以升" ,"华罗庚"};
1.1.2数组元素的引用
定义并用运算符new为之分配空间后,才可以引用数组中的每个元素;
1.1.3数组元素的默认初始化值
数组是引用类型,它的元素相当于类的成员变量,因此数组一经
分配空间,其中的每个元素也被按照成员变量同样的方式被隐式
初始化。
例如:
public class Test {
public static void main(String argv[]){
int a[]= new int[5];
System.out.println(a[3]); //a[3]的默认值为0
}
}
//运行结果:
//0
注意:
- 对于基本数据类型而言,默认初始化值各有不同
- 对于引用数据类型而言,默认初始化值为null(注意与0不同!)
如下图所示:
1.1.4创建基本类型数组
Java中使用关键字new来创建数组
例如:
public class Test{
public static void main(String args[]){
int[] s;//声明
s = new int[10];//初始化
//也可以直接int[] s=new int[10];
//基本数据类型数组在显式赋值之前,Java会自动给他们赋默认值。
for ( int i=0; i<10; i++ ) {
s[i] =2*i+1;
System.out.println(s[i]);
}
}
一维数组的结构图:
内存的简化结构
1.1.5初步认识Java虚拟机(JVM)
JVM 的内存被划分成了几个区域, 如图所示
程序计数器 (PC Register): 只是一个很小的空间, 保存下一条执行的指令的地址.
虚拟机栈(JVM Stack): 重点是存储局部变量表(当然也有其他信息). 我们刚才创建的 int[] arr 这样的存储地址的引用就是在这里保存.
本地方法栈(Native Method Stack): 本地方法栈与虚拟机栈的作用类似. 只不过保存的内容是Native方法的局部变量. 在有些版本的 JVM 实现中(例如HotSpot), 本地方法栈和虚拟机栈是一起的.
堆(Heap): JVM所管理的最大内存区域. 使用 new 创建的对象都是在堆上保存 (例如前面的 new int[]{1, 2, 3} )
方法区(Method Area): 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据. 方法编译出的的字节码就是保存在这个区域.
运行时常量池(Runtime Constant Pool): 是方法区的一部分, 存放字面量(字符串常量)与符号引用. (注意 从 JDK1.7 开始, 运行时常量池在堆上).
Native 方法:
JVM 是一个基于 C++ 实现的程序. 在 Java 程序执行过程中, 本质上也需要调用 C++ 提供的一些函数进行和操作系统底层进行一些交互. 因此在 Java 开发中也会调用到一些 C++ 实现的函数.这里的 Native 方法就是指这些 C++ 实现的, 再由 Java 来调用的函数
1.2二维数组的使用
1.2.1二维数组的初始化
二维数组[][]:数组中的数组
格式1(动态初始化) :
int[][] arr = new int[3][2];
// 定义了名称为arr的二维数组,
//二维数组中有3个一维数组
//每一个一维数组中有2个元素
//一维数组的名称分别为arr[0], arr[1], arr[2]
//给第一个一维数组1脚标位赋值为78写法是:
arr[0][1] = 78;
格式2(动态初始化) :
int[][] arr = new int[3][];
//二维数组中有3个一维数组。
//每个一维数组都是默认初始化值null (注意:区别于格式1)
//可以对这个三个一维数组分别进行初始化
arr[0] = new int[3];
arr[1] = new int[1];
arr[2] = new int[2];
//注:
int[][]arr = new int[][3]; //非法
格式3(静态初始化) :
int[][] arr = new int[][]{{3,8,2},{2,7},{9,0,1,6}};
//定义一个名称为arr的二维数组,二维数组中有三个一维数组
//每一个一维数组中具体元素也都已初始化
//第一个一维数组 arr[0] = {3,8,2};
//第二个一维数组 arr[1] = {2,7};
//第三个一维数组 arr[2] = {9,0,1,6};
//第三个一维数组的长度表示方式:
arr[2].length;
注意特殊写法情况:
- int[] x,y[]; x是一维数组,y是二维数组
- Java中多维数组不必都是规则矩阵形式
1.2.3二维数组的内存解析
这部分我们通过结合代码和图来理解
如下代码:
示例1:
int[][] arr = new int[3][];
arr[0] = new int[2];
arr[1] = new int[3];
arr[2] = new int[4];
其存储结构如下:
示例2:
int[][] arr1 = new int[4][];
arr1[1] = new int[]{1,2,3};
arr1[2] = new int[4];
arr1[2][1] = 30;
其内存结构图为:
示例3
int[][] arr4 = new int[3][];
System.out.println(arr4[0]);//null
System.out.println(arr4[0][0]);//报错
arr4[0] = new int[3];
arr4[0][1] = 5;
arr4[1] = new int[]{1,2};
其内存结构图为:
3数组中的常见操作
4.1数组转字符串
import java.util.Arrays
int[] arr = {1,2,3,4,5,6};
String newArr = Arrays.toString(arr);
System.out.println(newArr);
// 执行结果 [1, 2, 3, 4, 5, 6]
Java 中提供了 java.util.Arrays 包, 其中包含了一些操作数组的常用方法
实现一个自己版本的 toString
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6};
System.out.println(toString(arr));
}
public static String toString(int[] arr) {
String ret = "[";
for (int i = 0; i < arr.length; i++) {
// 借助 String += 进行拼接字符串
ret += arr[i];
// 除了最后一个元素之外, 其他元素后面都要加上 ", "
if (i != arr.length - 1) {
ret += ", ";
}
}
ret += "]";
return ret;
}
4.2数组拷贝
import java.util.Arrays
int[] arr = {1,2,3,4,5,6};
int[] newArr = Arrays.copyOf(arr, arr.length);
System.out.println("newArr: " + Arrays.toString(newArr));
arr[0] = 10;
System.out.println("arr: " + Arrays.toString(arr));
System.out.println("newArr: " + Arrays.toString(newArr)); // 拷贝某个范围.
int[] newArr = Arrays.copyOfRange(arr, 2, 4);
System.out.println("newArr2: " + Arrays.toString(newArr2));
注意事项: 相比于 newArr = arr 这样的赋值, copyOf 是将数组进行了 深拷贝, 即又创建了一个数组对象, 拷贝原有数组中的所有元素到新数组中. 因此, 修改原数组, 不会影响到新数组
深拷贝:必须将对象也拷贝一份
浅拷贝:数组内容是引用类型(地址),此时只能拷贝到地址,对象只是一个,依旧是修改同一个对象
拷贝的深浅要看拷贝对象。若为基本数据类型,则赋值就为深拷贝
实现自己版本的数组拷贝:
public static int[] copyOf(int[] arr){
int[] ret = new int[arr.length];
for (int i = 0; i < arr.length; i++){
ret[i] = arr[i];
}
return ret;
}
4.3查找数组中的指定元素
给定一个数组, 再给定一个元素, 找出该元素在数组中的位置.
4.3.1顺序查找
public static void main(String[] args){
int[] arr = {1,2,3,10,5,6};
System.out.println(find(arr, 10));
}
public static int find(int[] arr, int toFind) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == toFind) {
return i;
}
}
return -1; // 表示没有找到
}
// 执行结果 3
4.3.2二分查找
针对有序数组, 可以使用更高效的二分查找
以升序数组为例, 二分查找的思路是先取中间位置的元素, 看要找的值比中间元素大还是小. 如果小, 就去左边找; 否则就去右边找
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6};
System.out.println(binarySearch(arr, 6));
}
public static int binarySearch(int[] arr, int toFind) {
int left = 0;
int right = arr.length - 1;
while (left <= right){
int mid = (left + right) / 2;//取得中间元素
if (toFind < arr[mid]) { //去左侧区间找
right = mid - 1;
} else if(toFind > arr[mid]){
//去右侧区间找
left = mid + 1;
} else {
// 相等, 说明找到了
return mid;
}
}// 循环结束, 说明没找到
return -1;
}
// 执行结果 5
4.4数组排序(冒泡排序)
public static void main(String[] args){
int[] arr = {9, 5, 2, 7};
bubbleSort(arr);
System.out.println(Arrays.toString(arr));
}
public static void bubbleSort(int[] arr){
for (int i = 0; i < arr.length-1; i++){//趟数为长度-1
boolean flg = false;//每趟都会把flg重新置为false
for (int j=0; j<arr.length-1-i; j++){
if (arr[j - 1] > arr[j]){//检查整体是不是升序
int tmp = arr[j - 1];//若不是,交换;若是跳过
arr[j - 1] = arr[j];
arr[j] = tmp;
flg = true;//交换后将flg改为true
}
}
if(flg==false){
break;//有序,没有交换
}
} // end for
} // end bubbleSort
// 执行结果 [2, 5, 7, 9]
冒泡排序性能较低. Java 中内置了更高效的排序算法
public static void main(String[] args){
int[] arr = {9, 5, 2, 7};
Arrays.sort(arr);//调用相应的排序算法
System.out.println(Arrays.toString(arr));
}
4.5数组逆序
给定一个数组, 将里面的元素逆序排列.
思路:
设定两个下标, 分别指向第一个元素和最后一个元素. 交换两个位置的元素.
然后让前一个下标自增, 后一个下标自减, 循环继续即可.
这里我们以将一个升序序列逆序为例:
public static void main(String[] args){
int[] arr = {1, 2, 3, 4};
reverse(arr);
System.out.println(Arrays.toString(arr));
}
public static void reverse(int[] arr){
int left = 0;//指向第一个元素
int right = arr.length - 1;//指向最后一个元素
while (left < right){//交换
int tmp = arr[left];
arr[left] = arr[right];
arr[right] = tmp;
left++以上是关于Java中数组的使用的主要内容,如果未能解决你的问题,请参考以下文章