> 文章列表 > Java数组

Java数组

Java数组

Java基础数组

文章目录

  • 数组的概念
  • 数组的特点
  • 数组的分类
  • 使用一维数组
    • 静态初始化
    • 动态初始化
    • 一维数组的遍历
    • 数组元素的默认值
    • 一维数组内存分析
    • 一维数组在内存中的存储
  • 使用二维数组
    • 二维数组的遍历
    • 二维数组的默认初始化值
    • 二维数组的内存分析
  • 数组的一些操作
    • 扩容与缩容
    • 二分查找
    • 排序算法概述
    • 冒泡排序
  • Arrays 工具类的使用
  • 数组中的常见异常

数组的概念

数组(Array): 是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通 过编号的方式对这些数据进行统一管理。

数组的特点

  • 数组本身是引用数据类型,而数组中的元素可以是任何数据类型,包括基本数据类 型和引用数据类型。
  • 创建数组对象会在内存中开辟一整块连续的空间。占据的空间的大小,取决于数组的 长度和数组中元素的类型。
  • 数组中的元素在内存中是依次紧密排列的,有序的。
  • 数组,一旦初始化完成,其长度就是确定的。数组的长度一旦确定,就不能修改。
  • 我们可以直接通过下标(或索引)的方式调用指定位置的元素,速度很快。
  • 数组名中引用的是这块连续空间的首地址。

数组的分类

1、按照元素类型分:

  • 基本数据类型元素的数组:每个元素位置存储基本数据类型的值
  • 引用数据类型元素的数组:每个元素位置存储对象(本质是存储对象的首地址)

2、按照维度分:

  • 一维数组:存储一组数据
  • 二维数组:存储多组数据,相当于二维表,一行代表一组数据,只是这里的二维表每 一行长度不要求一样。

使用一维数组

1.数组的声明
//推荐
元素的数据类型 [] 一维数组的名称;
//不推荐
元素的数据类型 一维数组名[];

静态初始化

数组变量的初始化和数组元素的赋值操作同时进行,那就称为静态初始化。本质是用静态数据(编译时已知)为数组初始化。此时数组的长度由静 态数据的个数决定。

  • 方式一: 数据类型[] 数组名 = new 数据类型[]{元素 1,元素 2,元素 3,…};
  • 方式二: 数据类型[] 数组名;
    数组名 = new 数据类型[]{元素 1,元素 2,元素 3,…};

动态初始化

数组变量的初始化和数组元素的赋值操作分开进行,即为动态初始化。动态初始化中,只确定了元素的个数(即数组的长度),而元素值此时只是默认值,还并未真正赋自己期望的值。真正期望的数据需要后续单独一个一个赋值。

  • 数组存储的元素的数据类型[] 数组名字 = new 数组存储的元素的数据类型[长度];
  • 数组存储的数据类型[] 数组名字;
    数组名字 = new 数组存储的数据类型[长度];
    public static void main(String[] args) {//数组声明double[] prices;//数组初始化prices = new double[]{20.32,23.2};//静态初始化int[] arr = new int[]{1,2,3,4,5};//正确String[] foods;foods = new String[]{"韭菜"};//动态初始化String[] foods2 = new String[4];int[] foods3 = new int[5];int[] foods3;foods3 = new int[5];//其它方式int arr[] = new int[4];int[] arr1 = {1,2,3,4};int[] arr2 = {4};}

一维数组的遍历

	  int[] arr = {1,2,3,4};for (int i = 0; i < arr.length; i++) {System.out.println(arr[i]);}

数组元素的默认值

对于基本数据类型而言,默认初始化值各有不同。

数组元素类型 元素默认初始值
byte 0
short 0
int 0
long 0.0L
float 0.0F
double 0.0
char 0或‘\\u0000’
boolean false
引用类型 null

一维数组内存分析

为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。

将内存区域划分为5个部分:程序计数器虚拟机栈本地方法栈方法区

区域名称 作用
程序计数器 程序计数器是 CPU 中的寄存器,它包含每一个线程下一条要执行的指令的地址
虚拟 机栈 用于存储正在执行的每个 Java 方法的局部变量表等。局部变量表存 放了编译期可知长度
的各种基本数据类型、对象引用,方法执 行完,自动释放。
堆内存 存储对象(包括数组对象),new 来创建的,都存储在堆内存。
方法区 存储已被虚拟机加载的类信息、常量、(静态变量)、即时编译器编译后的代码等数据。
本地方法栈 当程序中调用了 native 的本地方法时,本地方法执行期间的内存区域

一维数组在内存中的存储


public static void main(String[] args) { int[] arr = new int[3]; System.out.println(arr);//[I@36baf30c
}
  • 执行main方法
  • 堆内存创建内存空间存储数组
  • 数组会有自己的内存地址(16进制表示)
  • 数组默认值0、0、0
  • JVM将数组的内存首地址赋值给引用类型变量arr

一维数组内存

赋值操作


public static void main(String[] args) { // 定义数组,存储 3 个元素int[] arr = new int[3]; //数组索引进行赋值arr[0] = 1;arr[1] = 2;arr[2] = 3;int[] arr2 = arr;arr2[1] = 4;
}

在这里插入图片描述

使用二维数组

二维数组声明的语法格式:
//推荐
元素的数据类型[][] 二维数组的名称;
//不推荐
元素的数据类型 二维数组名[][];
//不推荐
元素的数据类型[] 二维数组名[];

    public static void main(String[] args) {//静态初始化int[][] arr = new int[][]{{1,2,3},{4,5},{6,7,8,9}};int[][] arr;arr = new int[][]{{1,2,3},{4,5,6},{7,8,9,10}};//动态初始化String[][] arr6 = new String[3][4];double[][] arr7 = new double[2][];//其它写法int arr8[][] = new int[][]{{1,2,3},{4,5,6}};int[] arr9[] = new int[][]{{1,2,3},{4,5,6}};int arr10[][] = {{1,2,3},{4,5,6}}; //类型推断String arr11[][] = new String[3][4];}

二维数组的遍历

	  int arr[][] = new int[][]{{1,2,3},{4,5,6}};for (int i = 0; i < arr.length; i++) {for (int j = 0; j < arr[i].length; j++) {System.out.println(arr[i][j]);}}

二维数组的默认初始化值

  • 外层元素默认存储地址值
  • 内层元素按一维数组元素类型
public static void main(String[] args) {//第一种情况int[][] arr1 = new int[3][2];//外层元素System.out.println(arr1[0]);//[I@36baf30cSystem.out.println(arr1[1]);//[I@7a81197d//内层元素System.out.println(arr1[0][0]);//0String[][] arr2 = new String[3][2];//外层元素System.out.println(arr2[0]); //[Ljava.lang.String;@5ca881b5//内层元素System.out.println(arr2[0][1]); //null//第二种情况int[][] arr3 = new int[4][];//外层元素System.out.println(arr3[0]); //null//内层元素System.out.println(arr3[0][0]); //报错-空指针异常}

二维数组的内存分析

举例1:

public static void main(String[] args) {String[][] arr1 = new String[3][2];int[][] arr2  = new int[4][];arr2[1] = new int[5];arr2[1][1] = 1;arr2[2][2] = 1; //报错}

二维数组

举例2:

public static void main(String[] args) {int[][] arr1 = new int[3][]'arr1[0] = new int[3];arr1[1] = new int[]{1,2,3};arr1[0][1] = 1;arr1 = new int[2][];}

在这里插入图片描述

数组的一些操作

扩容与缩容

	int[] arr = new int[]{1,2,3,4,5};//扩容一倍int[] newArr = new int[arr.length << 1];//缩容 删除索引为 4 的元素int[] arr = {1, 2, 3, 4, 5, 6, 7};int delIndex = 4;for (int i = delIndex; i < arr.length - 1; i++) {arr[i] = arr[i + 1]; }arr[arr.length - 1] = 0;for (int i = 0; i < arr.length; i++) {System.out.println(arr[i]); //1、2、3、4、6、7、0}}

二分查找

int[] arr30 = new int[]{-99, -54, -2, 0, 2, 20};boolean flag = false;int value = -541;int head = 0;int end = arr30.length - 1;for (int i = 0; i < arr30.length; i++) {int middle = (head + end) / 2;if (arr30[i] == value) {System.out.println("找到了" + arr30[i] + "索引是" + i);flag = true;break;} else if (arr30[middle] > value) {end = middle - 1;} else {head = middle + 1;}}if (!flag) {System.out.println("没找到");}

排序算法概述

排序算法分类:内部排序和外部排序

  • 内部排序:整个排序过程不需要借助于外部存储器(如磁盘等),所有排序 操作都在内存中完成。
  • 外部排序:参与排序的数据非常多,数据量非常大,计算机无法把整个排 序过程放在内存中完成,必须借助于外部存储器(如磁盘)。外部排序最常 见的是多路归并排序。可以认为外部排序是由多次内部排序组成。
    Java数组
    常见时间复杂度所消耗的时间从小到大排序:
    O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n)

冒泡排序

int[] arr = {1, 3, 2, 1, -1, -1};for (int i = 1; i <= arr.length - 1; i++) {for (int j = 0; j < arr.length - i; j++) {if (arr[j] > arr[j + 1]) {int 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] + " ");}

Arrays 工具类的使用

java.util.Arrays 类即为操作数组的工具类,包含了用来操作数组(比如排序和搜索)的各种方法

  • 数组比较是否相等: Arrays.equals(arr1,arr2);
  • 输出数组元素信息 Arrays.toString(arr);
  • 将指定值填充到数组中: Arrays.fill(arr,10);
  • 使用快排: Arrays.sort(arr);
  • 二分查找元素: Arrays.binarySearch(arr,3);

数组中的常见异常

  • 数组角标越界异常(索引超出)
  • 空指针异常(为null时访问元素或方法报错NullPointerException)