1.数组的概念
1.1 概念:
数组概念:数组就是用于存储数据的长度固定的容器,保证多个数据的数据类型要一致
1.2 定义:
所谓数组(array),就是相同数据类型的元素按一定顺序排列的集合,就是把有限个类型相同的变量用一个名字命名,以便统一管理他们,然后用编号区分他们,这个名字称为数组名,编号称为下标或索引(index)。组成数组的各个变量称为数组的元素(element)。数组中元素的个数称为数组的长度(length)。
1.3 数组的分类:
1、按照维度分:
-
一维数组:存储一组数据
-
二维数组:存储多组数据,相当于二维表,一行代表一组数据,这是这里的二维表每一行长度不要求一样。
2、按照元素类型分:
-
基本数据类型的元素:存储数据值
-
引用数据类型的元素:存储对象(本质上存储对象的首地址)(这个在面向对象部分讲解)
注意:无论数组的元素是基本数据类型还是引用数据类型,数组本身都是引用数据类型。
2.一维数组的声明与使用
2.1 一维数组的声明
2.1.1 一维数组的声明/定义格式:
//推荐
元素的数据类型[] 数组名;
//不推荐
元素的数据类型 数组名[];
2.1.2 数组的声明,就是要确定:
(1)数组的维度:在Java中数组的标点符号是[],[]表示一维,[][]表示二维
(2)数组的元素类型:即创建的数组容器可以存储什么数据类型的数据。元素的类型可以是任意的Java的数据类型。例如:int, String等
(3)数组名:就是代表某个数组的标识符,数组名其实也是变量名,按照变量的命名规范来命名。数组名是个引用数据类型的变量,因为它代表一组数据。
示例:
public class ArrayCase2 {
public static void main(String[] args) {
// 数组的声明 两种方式!!!
int ageArr1[];
// 推荐使用下面这种!!!
⭐int[] ageArr2; // 存储一组整形的数据
// 存储一组浮点型数据
float[] score;
// 存储一组字符型数据
char[] hobby;
}
}
2.2 一维数组初始化格式(有两种)
一、静态初始化(两种):
-
什么是初始化?
-
初始化就是确定数组元素的总个数(即数组的长度)和元素的值
-
-
什么是静态初始化?
-
静态初始化就是用静态数据(编译时已知)为数组初始化。此时数组的长度由静态数据的个数决定。
-
2.2.1 格式一:
数据类型[] 数组名 = {元素1,元素2,元素3...};//必须在一个语句中完成,不能分开两个语句写
2.2.2 格式二:
数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3...};
或
数据类型[] 数组名;
数组名 = new 数据类型[]{元素1,元素2,元素3...};
二、动态初始化
2.2.3 格式:
数组存储的元素的数据类型[] 数组名 = new 数组存储的元素的数据类型[长度];
或
数组存储的数据类型[] 数组名;
数组名字 = new 数组存储的数据类型[长度];
-
new:关键字,创建数组使用的关键字。因为数组本身是引用数据类型,所以要用new创建数组对象。
-
[长度]:数组的长度,表示数组容器中可以存储多少个元素。
-
注意:数组有定长特性,长度一旦指定,不可更改。和水杯道理相同,买了一个2升的水杯,总容量就是2升是固定的。
示例:
// 声明数组的方法(存储 5 个整数的数组容器)
// 静态初始化
int[] arr1 = {1, 2, 3, 4, 5};
int[] arr2 = new int[]{1, 2, 3, 4, 5};
int[] arr3;
arr3 = new int[]{1, 2, 3, 4, 5};
// 动态初始化
int[] arr4 = new int[5];
int[] arr5;
arr5 = new int[5];
2.3 一维数组的使用
2.3.1 数组的长度属性:
数组的长度属性: 每个数组都具有长度,而且是固定的,Java中赋予了数组的一个属性,可以获取到数组的长度,语句为:数组名.length
,属性length的执行结果是数组的长度,int类型结果。
数组名.length
2.3.2 表示数组中的一个元素:
每一个存储到数组的元素,都会自动的拥有一个编号,从0开始,这个自动编号称为数组索引(index)或下标,可以通过数组的索引/下标访问到数组中的元素。
数组名[索引/下标]
2.3.3 下标范围:
Java中数组的下标从[0]开始,下标范围是[0, 数组的长度-1],即[0, 数组名.length-1]
示例:
public class ArrayCase3 {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
System.out.println("arr数组的长度:" + arr.length);
System.out.println("arr数组的第1个元素:" + arr[0]);//下标从0开始
System.out.println("arr数组的第2个元素:" + arr[1]);
System.out.println("arr数组的第3个元素:" + arr[2]);
//修改第1个元素的值
//此处arr[0]相当于一个int类型的变量
arr[0] = 100;
System.out.println("arr数组的第1个元素:" + arr[0]);
}
}
2.3.4 数组下标越界异常:
当访问数组元素时,下标指定超出 [0, 数组名.length-1] 的范围时,就会报数组下标越界异常:ArrayIndexOutOfBoundsException。
2.4 一维数组的遍历
数组遍历: 就是将数组中的每个元素分别获取出来,就是遍历。遍历也是数组操作中的基石。for循环与数组的遍历是绝配。
示例:
public class ArrayCase5 {
public static void main(String[] args) {
int[] int = {1, 2, 3, 4, 5};
// 循环输出数组 int
for (int i = 0; i < int.length; i++) {
System.out.println(int[i]);
}
}
}
2.5 数组元素的默认值
当我们使用动态初始化方式创建数组时,元素只是默认值。
3.一维数组内存解析
3.1 内存概述
内存是计算机中重要的部件之一,它是与CPU进行沟通的桥梁。其作用是用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器交换的数据。只要计算机在运行中,CPU就会把需要运算的数据调到内存中进行运算,当运算完成后CPU再将结果传送出来。我们编写的程序是存放在硬盘中的,在硬盘中的程序是不会运行的,必须放进内存中才能运行,运行完毕后会清空内存。
Java虚拟机要运行程序,必须要对内存进行空间的分配和管理。
3.2 Java虚拟机的内存划分
为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
区域名称 | 作用 |
---|---|
程序计数器 | 程序计数器是CPU中的寄存器,它包含每一个线程下一条要执行的指令的地址 |
本地方法栈 | 当程序中调用了native的本地方法时,本地方法执行期间的内存区域 |
方法区 | 存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。 |
堆内存 | 存储对象(包括数组对象),new来创建的,都存储在堆内存。 |
虚拟机栈 | 用于存储正在执行的每个Java方法的局部变量表等。局部变量表存放了编译期可知长度的各种基本数据类型、对象引用,方法执行完,自动释放。 |
3.3 数组下标为什么是0开始
因为第一个元素距离数组首地址间隔0个单元格。
3.4 两个一维数组内存图
两个数组独立
public static void main(String[] args) {
int[] arr = new int[3];
int[] arr2 = new int[2];
System.out.println(arr);
System.out.println(arr2);
}
4.一维数组的常见方法
4.1 数组统计:求总和、均值、统计偶数个数、乘积等
求总和:
public class ArrayCase15 {
public static void main(String[] args) {
int[] arr1 = new int[]{2, 4, 1, 6, 7};
// 总和及均值
int sum = arr1[0];
for (int i = 1; i < arr1.length; i++) {
sum += arr1[i];
}
System.out.println("总和为:" + sum);
System.out.println("均值为:" + (double) (sum / arr1.length));
}
}
偶数个数:
public class ArrayCase15 {
public static void main(String[] args) {
// 偶数个数
int count = 0;
for (int i = 1; i < arr1.length; i++) {
if (arr1[i] % 2 == 0) {
count++;
}
}
System.out.println("偶数个数为:" + count);
}
}
乘积:
public class ArrayCase15 {
public static void main(String[] args) {
// 总乘积
int tot = arr1[0];
for (int i = 1; i < arr1.length; i++) {
tot *= arr1[i];
}
System.out.println("总乘积为:" + tot);
}
}
4.2 数组找最值
4.2.1 找最大值/最小值
通过记录值:
public class ArrayCase11 {
public static void main(String[] args) {
int[] arr1 = new int[]{13, 26, 32, 14, 25};
int max = arr1[0];
int min = arr1[0];
for (int i = 1; i < arr1.length; i++) {
// 求最大值
if (max < arr1[i]) {
max = arr1[i];
}
// 求最小值
if (min > arr1[i]) {
min = arr1[i];
}
}
System.out.println("最大值是:" + max);
System.out.println("最大值是:" + min);
}
}
通过记录下标:
public class ArrayCase11 {
public static void main(String[] args) {
int[] arr1 = new int[]{13, 26, 32, 14, 25};
int maxIndex = 0;
int minIndex = 0;
for (int i = 1; i < arr1.length; i++) {
// 求最大值
if (arr1[maxIndex] < arr1[i]) {
maxIndex = i;
}
// 求最小值
if (arr1[minIndex] > arr1[i]) {
minIndex = i;
}
}
System.out.println("最大值是:" + arr1[maxIndex]);
System.out.println("最大值是:" + arr1[minIndex]);
}
}
4.2.2 找最值及其第一次出现的下标
public class ArrayCase13 {
public static void main(String[] args) {
int[] arr1 = new int[]{13, 26, 32, 14, 25};
int maxIndex = 0;
int minIndex = 0;
for (int i = 1; i < arr1.length; i++) {
// 求最大值及下标
if (arr1[maxIndex] < arr1[i]) {
arr1[maxIndex] = arr1[i];
maxIndex = i;
}
// 求最小值及下标
if (arr1[minIndex] > arr1[i]) {
arr1[minIndex] = arr1[i];
minIndex = i;
}
}
System.out.println("最大值是:" + arr1[maxIndex] + ",下标为:" + maxIndex);
System.out.println("最大值是:" + arr1[minIndex] + ",下标为:" + minIndex);
}
}
4.3 逆序输出
public class ArrayCase14 {
public static void main(String[] args) {
int[] arr1 = new int[]{2, 4, 1, 6, 7};
for (int i = arr1.length - 1; i >= 0; i--) {
System.out.print(arr1[i]);
}
// 逆序
String outarr = "[";
for (int i = arr1.length - 1; i >= 0; i--) {
if (i == arr1.length - 1) {
outarr += arr1[i];
} else {
outarr += "," + arr1[i];
}
}
outarr += "]";
System.out.println(outarr);
}
}
4.4 数组的元素查找
4.4.1 顺序查找
顺序查找:挨个查看
要求:对数组元素的顺序没要求
示例代码:
public class ArrayCaseOrderSearch18 {
public static void main(String[] args) {
int[] arr = new int[]{2, 4, 1, 6, 7, 9, 3, 8, 5};
// 索引下标
Scanner scan = new Scanner(System.in);
System.out.print("请输入你要查找的数字:");
int num = scan.nextInt();
scan.close();
// 目标值的下标
int Index = -1;
for (int i = 0; i < arr.length; i++) {
if (num == arr[i]) {
Index = i;
break;
}
}
if (Index == -1) {
System.out.println("你输入的不存在!");
} else {
System.out.println("你要查找的是:" + num + ",第一次出现的索引下标为:" + Index + ",数组总长度为:" + arr.length);
}
}
}
4.4.2 二分查找
public class ArrayCaseDinarySearch19 {
public static void main(String[] args) {
// 二分查找(折半查找)
int[] arr = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9};
// 输入
Scanner scan = new Scanner(System.in);
System.out.print("请输入你要查找的数字:");
int target = scan.nextInt();
scan.close();
// 目标值的下标
int index = -1;
// 起始下标位
int left = 0;
// 结束下标位
int right = arr.length - 1;
while (left <= right) {
int mid = (left + right) / 2;
// 判断比较
if (arr[mid] == target) {
index = mid;
break;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
if (index != -1) {
System.out.println("找到目标值:" + target + ",索引下标为:" + index);
} else {
System.out.println("你输入的目标值不存在!");
}
}
}
4.5 数组元素排序
4.5.1排序算法概述
数组的排序算法很多,实现方式各不相同,时间复杂度、空间复杂度、稳定性也各不相同:
-
时间复杂度:
常见的算法时间复杂度由小到大依次为:Ο(1)<Ο(log2n)<Ο(n)<Ο(nlog2n)<Ο(n2)<Ο(n3)<…<Ο(2n)<Ο(n!)
4.5.2 选择排序
public class SelectOrder20 {
public static void main(String[] args) {
// 选择排序(从小到大排)
// 目标元素设定位置,按照目标的本来元素和目标元素后面的元素进行比较,直到尾部
// 当比较一轮之后,记录最小值的索引与目标位置进行交换
int[] arr = {6, 3, 12, 4, 8};
// 按照循环设定目标位置
for (int i = 0; i < arr.length; i++) {
int min = arr[i];
int index = i;
// 与目标位后面的元素一一比对
for (int j = i + 1; j < arr.length; j++) {
if (arr[j] < min) {
min = arr[j];
index = j;
}
}
int temp;
if (index != i) {
// 中间变量交换
temp = arr[i];
arr[i] = arr[index];
arr[index] = temp;
}
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
}
4.5.3 冒泡排序及优化
public class BubbleOrder21 {
public static void main(String[] args) {
// 冒泡排序 两两交换
// 由小到大排序
int[] arr = {6, 3, 12, 4, 8};
int count = 0;
int tang = 0;
for (int i = 0; i < arr.length - 1; i++) {
boolean flag = true;
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j + 1] < arr[j]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
flag = false;
}
count++;
}
if (flag) {
break;
}
System.out.println("次数:" + count);
tang++;
}
System.out.println("趟数:" + tang);
System.out.println(Arrays.toString(arr));
}
}
5.二维数组
概述:数组中套多个数组
5.1 二维数组的静态初始化(两种格式)
5.1.1 格式一:
int[] arr1 = {1, 2, 3, 4, 5};
5.1.2 格式二:
int[][] secArr2 = new int[][]{{1, 2}, {3, 4}, {5, 6}};
// 格式二的另一种写法
int[][] secArr3;
secArr3 = new int[][]{{1, 2}, {3, 4}, {5, 6}};
5.2 获取二维数组的长度
格式:数组名.length
public static void main(String[] args) {
int[][] secArr1 = {{1, 2}, {3, 4, 5}, {6, 7, 8, 9}};
// 二维数组的长度
System.out.println(secArr1.length);
}
5.3获取二维数组中的元素
格式:数组名
[i][j]
i:代表的是一维数组在二维数组中的索引位置
j:代表的是元素在一维数组中的索引位置
遍历方法:
1.先遍历二维数组,将每一个一维数组遍历出来
2.再遍历每一个一维数组,将元素获取出来
public static void main(String[] args) {
// 二维数组 静态初始化
int[][] secArr1 = {{1, 2}, {3, 4, 5}, {6, 7, 8, 9}};
// 第一层拿到数组的长度进行遍历
for (int i = 0; i < secArr1.length; i++) {
// 然后根据里层数组的长度再次进行遍历
for (int j = 0; j < secArr1[i].length; j++) {
System.out.print(secArr1[i][j] + " ");
}
System.out.println(" ");
}
}
5.4 二维数组的动态初始化
1.概述:数组中的套多个数组
2.定义格式
a.动态初始化
数据类型[][] 数组名 = new 数据类型[m][n]
数据类型 数组名[][] = new 数据类型[m][n]
数据类型[] 数组名[] = new 数据类型[m][n]
m:代表的是二维数组的长度
n:代表的是二维数组中每一个一维数组的长度
public class SecArrayitra3 {
public static void main(String[] args) {
// 二维数组 动态初始化
int[][] secArr1 = new int[3][2];
Scanner scan = new Scanner(System.in);
// 第一层拿到数组的长度进行输入
for (int i = 0; i < secArr1.length; i++) {
// 然后根据里层数组的长度再次进行输入
for (int j = 0; j < secArr1[i].length; j++) {
System.out.print("请输入第" + i + "行" + "第" + j + "列的数字:");
secArr1[i][j] = scan.nextInt();
}
System.out.println(" ");
}
for (int i = 0; i < secArr1.length; i++) {
for (int j = 0; j < secArr1[i].length; j++) {
System.out.print(secArr1[i][j] + " ");
}
System.out.println(" ");
}
}
}
后续内容,正在更新...