前言
如果数据(变量)过于分散,就不便于统一管理。
容器可以把多个相同数据类型的数据(变量)集中组织到一起,便我于们对多个数据进行统一管理。
容器有以下特点:
- 容器可以保存多个数据类型相同的元素
- 容器的大小固定不可改变
一、数组的概念
Java中的容器有很多种,而数组就是容器的一种,数组具有容器的所有特点。
- 数组中可以保存多个相同数据类型的元素。
- 数组的长度一旦确定不可以改变。
二、数组的2种声明方式
Java有2种声明数组的方法,1种继承自C语言,另一种是目前Java中主流的数组声明方式。
1.C语言数组声明风格(不建议使用)
int array2[];
2.Java数组声明风格
int array2[];
三、数组的2种初始化方式
和Python不同Java是强类型语言,如果想要使用变量必须声明变量的数据类型。
为了避免在写代码的过程中反复声明变量数据类型,变量声明 和 初始化(赋值))可以分成2步,也就是先声明,再初始化(赋值)。
Java中有整数、字符、布尔、字符串、空(null)6种常量,空常量不能打印。
空常量和基本数据类型没关系(基本数据类型在栈中存储),使用空常量(null)可以给引用数据类型的对象引用进行赋值。
如果数组只声明 不初始化(赋值),该数组的引用会在栈空间中指向常量null,并不会开辟堆内存空间;
如果数组没有指向任何堆内存地址值, 我们还试图去使用该数组时,就会出现空指针异常。
1.动态初始化数组
byte[] byteArray = new byte[3];//当初始化数组时,数组长度可以设置为变量、运算结果。 int length = 3; int[] intArray = new int[length];
2.静态初始化数组
如果创建数组时,如果可以直接确定数组中的内容,可以静态初始化数组。
相较于动态初始化数组,静态初始化数组方式不需要指定数组长度,JVM会自动根据{}中元素的个数,自动推导出数组长度。
静态初始化数组分为完整格式初始化和简化格式初始化2种方法。
A.完整格式初始化数组
数组静态初始化:创建数组时,直接确定数组元素。(不需要指定数组的长度JVM会根据{}中元素的个数自动推导出数组长度)
//静态初始化数组 byte[] byteArray = new byte[]{1, 2, 3};
B.简化格式初始化数组
虽然静态简化初始化的格式不需要有new,但是底层仍然有开辟空间的过程。
//静态初始化简化版,底层依然new了开辟了内存空间
int[] intArray = {1011, 1024};
注意:
通过静态初始话数组简化格式,只能一步就完成数组的声明和初始化,无法对已经声明的数组再进行初始化。
int[] intArray; intArray = new int[2]; //动态初始化数组 intArray = new int[]{10, 29,22}; //静态初始化数组(完整格式) //intArray = {1, 2, 3} //静态初始化数组(简化格式)无法对提前声明的数组进行初始化。
Java字节码存储在硬盘中,一旦程序需要运行起来Java虚拟机会把程序加载到内存中,以供CPU快速执行程序。
为了提升运算效率,JVM对申请的内存空间进行不同区域划分,每一片区域都有特定的处理数据方式和内存管理方式。
- 寄存器:CPU获取和存储数据的内存,给CPU使用。
- 本地方法栈:JVM使用操作系统功能时使用。
- 方法区:存储可以运行的class文件
- 堆内存:存储对象或者数组,new出来的都存储在堆内存
- 栈内存:方法执行时使用的内存空间,比如main方法运行,进入方法栈中执行。
int[] intArray1=new int[]{1,23,66};
Java的基本数据类型保存在栈内存,引用数据类型保存在堆内存。
intArray1时JVM会把先main方法加载到栈内存执行。
执行到方法中new语法时,开辟一块堆内存存储数据{1,23,66}这块真正存储数据的堆内存空间称为对象。
intArray1在栈内存中保存了对象(堆内存)的内存地址值,固intArray1为对象的引用。
五、数组元素的访问方式
Java数组只对外提供了1种访问方式-索引方式,索引-数组中元素的编号,该编号(索引)默认从0开始,正序递增,恒为正数。
只有通过数组的索引,才能设置和获取数组中的元素,因此索引才是实现数组元素统一管理的核心,
数组元素求和、求最大、求最小、求均值以及排序操作,都是通过for循环生成正确的数组索引实现的。
1.数组元素排序
public class ArrayDemo15 { public static void main(String[] args) { int[] intArrary = {18, 20, 15, 17}; for (int i = 0; i < intArrary.length; i++) { int currentMax; for (int j = i + 1; j < intArrary.length; j++) { if (intArrary[i] > intArrary[j]) { currentMax = intArrary[i]; intArrary[i] = intArrary[j]; intArrary[j] = currentMax; } } } System.out.println(Arrays.toString(intArrary)); } }
2.获取数组中的最大值和最小值
获取数组中最大值和最小值是需使用2个独立的if分支。
在1次for循环中判断2次,1次判断当前最大值,另一1次判断当前最小值,因为比当前最大值的数小的数,不一定就是整个数组中最小的数。
//获取数组中的最大值和最小值。----【纪念2017年冬,地铁13号线望京西 面试】 public class ArrayDemo14 { public static void main(String[] args) { int[] intArray = new int[]{-11, 8115, 12, -117, -20}; int maxNumber = intArray[0]; int minNumber = intArray[0]; for (int i = intArray.length - 1; i >= 0; i--) { int currentElement = intArray[i]; //1.要使用2个独立的if分支 if (currentElement > maxNumber) { maxNumber = currentElement; } /* 2.不能在此处直接使用else{因为比当前最大的数小的数,不一定就是整个数组中最小的数字 } 因此需要1次for循环需要判断2次,1次判断当前最大,1次判断当前最小 */ if (currentElement < minNumber) { minNumber = currentElement; } } System.out.println("当前数组的最大值" + maxNumber); System.out.println("当前数组的最小值" + minNumber); }
3.数组append元素
在Java中数组长度是固定的,需要创建新的数组实现;
package ArryOpration; import java.util.Arrays; public class TestArray { public static void main(String[] args) { String[] l1 = {"我", "是"}; String[] l2 = {"张", "根"}; String[] l3 = new String[l1.length + l2.length]; for (int i = 0; i < l1.length; i++) { l3[i] = l1[i]; } for (int i = 0; i < l2.length; i++) { l3[l1.length + i] = l2[i]; } //把l3的内存地址赋值给l1 l1=l3; System.out.println(Arrays.toString(l1)); } }
4.数组remove元素
在Java中数组长度是固定的,需要创建新的数组实现;
re-重新-move移动,重新移动了=删除;
方案1:
package ArryOpration; import java.util.Arrays; //删除数组中的某个元素 public class TestArray01 { public static void main(String[] args) { int[] array1 = {3, 4, 5, 6, 2, 7, 8, 9}; //删除索引为2的元素 int del_index = 2; //step1:从删除的位置开始,向前移动元素 for (int i = del_index; i < array1.length - 1; i++) { array1[i] = array1[i + 1]; } //step2:将最后1个闲置位的元素,置为0; array1[array1.length - 1] = 0; System.out.println(Arrays.toString(array1)); } }
方案2:
package ArryOpration; import java.util.Arrays; public class TestArray02 { public static void main(String[] args) { int[] array1 = {1, 9, 9, 8, 0, 5, 8, 9}; //删除索引为5的元素 int del_index = 5; //step1:创建1个新的数组 int[] new_array = new int[array1.length - 1]; //step2:移动目标索引之前的元素; for (int i = 0; i < del_index; i++) { new_array[i] = array1[i]; } System.out.println(Arrays.toString(new_array)); //step3:移动目标索引之后的元素; for (int i = del_index + 1; i < array1.length; i++) { new_array[i - 1] = array1[i]; } //step4:使array1栈内存存储的引用地址和new_array相同; array1 = new_array; System.out.println(Arrays.toString(array1)); } }
5.冒泡排序
我们喝汽水的时候,由于二氧化碳比水轻,汽水里面会不断有小气泡,向上浮到汽水上面。
冒泡排序算法可以将集合中的 每一个数字元素都像小气泡一样,一点一点地向数组的一侧(右侧/左侧)移动。
冒泡排序核心思想:让数组中相邻的2个数字元素,进行两两比较,根据大小交换位置,使较大数字元素逐渐向一侧移动。
package com.itheima.sort; import java.util.Arrays; //基本排序-冒泡排序 /* *我们喝汽水的时候,由于二氧化碳比水轻,汽水里面会不断有小气泡,向上浮到汽水上面。 *冒泡排序算法可以将集合中的 每一个数字元素都像小气泡一样,一点一点地向数组的一侧(右侧/左侧)移动。 * 冒泡排序核心思想:让数组中相邻的2个数字元素,进行两两比较,根据大小交换位置,使较大数字元素逐渐向一侧移动。 * */ public class BubbleSortDemo1 { public static void main(String[] args) { int[] intArray = {5, 8, 6, 3, 92, 1, 7}; for (int i = 0; i < intArray.length - 1; i++) { //相邻的两个元素进行大小对比 if (intArray[i] > intArray[i + 1]) { //交换位置 int temp = intArray[i]; intArray[i] = intArray[i + 1]; intArray[i + 1] = temp; } } /* *1次循环(打擂)只能在组中确定1个座次(按大小排序的座次)(内循环) *执行数组长度-1次循环就可以完成数组中所有数字元素的排位(外循环) */ for (int i = 0; i < intArray.length; i++) { for (int j = 0; j < intArray.length - i - 1; j++) { //相邻的两个元素进行大小对比 if (intArray[j] > intArray[j + 1]) { //交换位置 int temp = intArray[j]; intArray[j] = intArray[j + 1]; intArray[j + 1] = temp; } } System.out.println(Arrays.toString(intArray)); } } }
六、Arrays数组工具类
JRE提供了1个叫Arrays的工具类,封装了排序、查找极值、遍历输出等功能,可以帮助我们对数组进行操作;
package ArryOpration; import java.util.Arrays; public class TestArray { public static void main(String[] args) { int[] bag2 = new int[]{6, 17, 82, 9, 10}; //显示数组 int[][] bag1 = new int[][]{{1, 2}, {3, 4}}; for (int[] a : bag1) { System.out.println(Arrays.toString(a)); } System.out.println(Arrays.toString(bag1)); System.out.println(Arrays.toString(bag2)); //通过二分法,对数组进行排序然后再获取元素的索引 Arrays.sort(bag2); System.out.println(Arrays.toString(bag2)); System.out.println(Arrays.binarySearch(bag2, 9)); //切片数组中的元素 int[] new_array = Arrays.copyOf(bag2, 4); System.out.println(Arrays.toString(new_array)); //区间切片 int[] new_array1 = Arrays.copyOfRange(bag2, 1, 4); System.out.println(Arrays.toString(new_array1)); //判断2个数组中的值是否相等? int[] array1 = {1993, 0}; int[] array2 = new int[]{1993, 0}; System.out.println(Arrays.equals(array1, array2)); //从数组1中复制元素到数组2 int[] src_array = new int[]{1, 2, 3, 4}; int[] des_array = new int[10]; //将源数组下标位1开始,复制到目标数组的下标3,一共复制3个元素 System.arraycopy(src_array, 1, des_array, 3, 3); System.out.println(Arrays.toString(des_array)); } }
七、二维数组
在机器学习中数据集最终会变成1个数字类型二维数组;
但是我在Python里定义二维数组时,思维是由外至内的;[ [1,2,3],[2,4,5,9] ];
在Java中定义二维数组时思维是由内向外:1个int圈起来=int[]=数组,再把数组圈起来=int[][]=1个二维数组;
package ArryOpration; import java.util.Arrays; public class TestArray { public static void main(String[] args) { String[][][][] a1 = {{{{}}}}; System.out.println(Arrays.toString(a1)); } }
参考