数组(Array
)
数据结构
存储数据的结构方式。存储数据的结构方式不一样,直接涉及到数据的增删改查的效率不一样
常见的数据结构
包含:数组、队列、链表、树、哈希表、栈…
数组:查询快,增删慢
队列、链表、栈:增删快,数据量小的时候
哈希表:增删改查很快,无序的
树:增删改查很快,有序的
数组的定义
数组是一个存储相同数据类型的有序集合| 容器,数组属于引用数据类型
数组的索引|下标从0开始递增
public class ForAndArrayTest{
public static void main(String[] args){
int arr[] = new int[]{1,2,3,4,5};
for(int i = 0;i < arr.length;i++){
System.out.println(arr[i]);
}
}
}
特点:相同数据类型、有序的
画图分析:
虚拟机上的内存分为栈内存,堆内存
栈内存
存储:局部变量
若是基本数据类型的局部变量,栈内存中存储的是数据值
若是引用数据类型的局部变量,栈内存中存储的是对象在堆中的地址
特点:
-
栈内存遵守“
先进后出,后进先出
”的特点 -
栈内存是一块连续的存储空间,由虚拟机分配,效率高
画图分析:
-
每个线程都拥有一个独立的栈内存,避免了数据干扰,用于存放该线程执行方法的信息
单线程同步:同一时间只能做一件事情
堆内存
存储:所有引用数据类型,包括new出来的对象和数组
特点:
-
堆内存不是块连续的存储空间,分配灵活,效率低
画图分析:
-
多个线程共享一个堆内存,被所有的线程共享
多线程异步:同一时间可以做多件事情
补充:在方法体或代码块中定义的变量,称为局部变量
目前见过的异常有哪些?
-
空指针异常(
java.lang.NullPointerException
)引起:对空对象执行某些操作时,就会引发
NullPointerException
空指针异常比如:操作数组中元素时,首先应该检查该数组是否引用了堆中对象的地址
代码展示:
public class MakeException2{ public static void main(String[] agrs){ int arr1[] = {1,2,3,4}; int arr2[] = arr1; arr1 = null; System.out.println(arr1[0]); // NullPointerException System.out.println(arr2[2]); // 3 } }
画图分析:
运行错误截图:
-
数组索引越界异常(
java.lang.ArrayIndexOutofBoundsException
)引起:操作数组的索引值越界,索引值合法取值范围是[0,数据长度-1]
代码展示:
public class ArrayIndexOutofBoundsExceptionTest{ public static void main(String[] args){ int arr[] = {1,2,3,4,5}; System.out.println(arr[5]); } }
运行错误截图:
-
算术异常(
java.lang.ArithmeticException
)引起:分母为0
代码展示
public class MakeException1{ public static void main(String[] args){ int a = 1 / 0; System.out.println(a); } }
运行错误截图:
-
输入类型不匹配异常(
inputMismatchException
)代码展示
import java.util.Scanner; public class ScannerTest03{ public static void main(String[] args){ System.out.println("请输入整数:"); int num = new Scanner(System.in).nextInt(); System.out.println("这个数为num = " + num); } }
运行错误截图:
数组的核心特点
- 数组是一块连续的存储空间
- 数组一旦创建成功,那么空间长度就不能改变了
数组的优势
查询效率是所有数据结构中最高的
数组的劣势
数组执行插入、删除操作时,效率低
代码展示:
public class ArrayDemo03{
public static void main(String[] args){
int arr1[] = {1,2,3,4,5};
int[] arr2 = arr1;
arr2[2] = 33;
System.out.println(arr1[2]); // 输出33
}
}
画图分析:
运行截图:
代码展示:
public class ArrayDemo04{
public static void main(String[] args){
int[] arr = {11,22,33,44,55};
arr[1] = 222;
arr[4] = 555;
System.out.println(arr[0]); // 11
System.out.println(arr[1]); // 222
}
}
运行截图:
画图说明:
核心总结:删除插入慢,查询修改快
掌握以下两点:
-
为什么索引从0开始递增?
-
为什么数组的查询效率最高?
答:因为课通过公司快速寻址,课快速找到元素所对应的功能
删除数组元素的操作
错误分析:
若像以上如此删除数组中的元素,那“数组是块连续的存储空间”就不成立了
正确的实现步骤:
- 把删除元素及其之后的所有元素往前挪动一位
- 最为一位元素的默认值为默认值,比如int类型默认值为0
需求:
- 删除数组{5, 12, 90, 18, 77, 76, 45, 28, 59, 72}索引为2的元素,删除后:{5, 12, 18, 77, 76, 45, 28, 59, 72,0}。
代码展示:
public class DelArray{
public static void main(String[] args){
int arr = {11,15,16,45,78,45,90,12,17};
int index = 2;
for(int i = index;i < arr.length - 1;i++){
arr[i] = arr[ i + 1];
}
arr[arr.length - 1] = 0;
for(int temp : arr){
System.out.print(temp + " ")
}
}
}
画图分析:
运行截图:
插入数组元素的操作
错误分析:
以上这样直接插入数组元素是不正确的,这样做“”数组以一块连续的存储空间“就不成立了
正确的实现步骤:
- 检查元素是否需要扩容,当数组空间长度和实际存放元素的个数相等时,就要扩容
- 新建一个比原数组空间长度更大的新数组,新数组空间长度由需求而定
- 把元素中的元素拷贝一份到新数组中
- 让原数组保存新数组的地址
- 把插入索引及其之后所有元素从后往前挪动一位
- 把需插入的元素赋值到新插入索引的位置
代码展示:
public class InsertElement{
public static void main(String[] args){
int arr[] = {11,15,16,45,78,45,90,12,17};
int index = 2;
int size = 9;
int value = 222;
if(arr.length == size){
int newArr[] = new int[arr.length + 1];
for(int i = 0;i < arr.length;i++){
newArr[i] = arr[i];
}
for(int temp : arr){
System.out.println(temp);
}
arr = newArr;
}
for(int i = arr.length - 2;i >= index;i--){
arr[i+1] = arr[i];
}
arr[index] = value;
System.out.print("插入新元素后,遍历数组中的元素:");
for(int temp:arr){
System.out.print(temp + " ");
}
}
}
画图分析:
运行截图:
需求:
- 将数组反序输出,原数组{5, 12, 90, 18, 77, 76, 45, 28, 59, 72},反序输出后{72,59,28,45,76,77,18, 90,12,5}。
画图分析:
代码展示:
// 方式一:
public class ReverseArrayElement{
public static void mian(String[] args){
int arr[] = {5, 12, 90, 18, 77, 76, 45, 28, 59, 72};
for(int i = 0; i< arr.length / 2 ;i++){
int temp = arr[i];
arr[i] = arr[arr.length - 1 - i];
arr[arr.length - 1 - i] = temp;
}
for(int temp: arr){
System.out.print(temp + " ");
}
}
}
运行截图:
画图分析:
代码展示:
public class ReverseArrayTest{
public static void main(String[] args){
int arr[] = {5, 12, 90, 18, 77, 76, 45, 28, 59, 72};
int newArr[] = new int[arr.length];
for(int i = 0;i < arr.length;i++){
newArr[arr.length - i - 1] = arr[i];
}
for(int temp : newArr){
System.out.print( temp + " ");
}
}
}
运行截图:
补充知识:直接输出数组,得到的是数组第一个元素的首地址
代码展示:
public class AddressTest{
public static void main(String[] args){
int arr[] = {1,11,12,13,15};
System.out.println(arr); // 输出的是数组第一个元素的首地址
}
}
画图分析:
运行截图:
代码展示:
public class AddressTest1{
public static void main(String[] arhs){
char arr[] = {'a','b','c','d'};
System.out.println(arr);
}
}
运行截图:
冒泡排序法
算法核心:相邻两个元素做比较,若前一个元素> 后一个元素,则两元素交换位置
排序过程总结:每一趟相邻两个元素比较完毕,都能确定一个最大值
需求:使用冒泡排序实现对 int[] arr ={3,5,1,7,6,2,4} 数组进行升序排序
画图分析:
代码展示:
public class ArraySortTest{
public static void main(String[] args){
int arr[] ={3,5,1,7,6,2,4};
for(int i = 0;i< arr.length - 1;i++){
for(int j = 0;j< arr.length - 1 - i;j++){
if(arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
for(int temp : arr){
System.out.print(temp + " ");
}
}
}
运行截图:
练习:
-
获取数组{5, 12, 90, 18, 77, 76, 45, 28, 59, 72}的最大值,也就是该数组的元素90。
代码展示:
public class MaxValue{ public static void main(String[] args){ int arr[] = {5,12,90,18,77,76,45,28,59,72}; int max = arr[0]; for(int i = 1;i<arr.length; i++){ if(max < arr[i]){ max = arr[i]; } } System.out.print("最大值为"+max); } }
运行截图:
-
获取数组{5, 12, 90, 18, 77, 76, 45, 28, 59, 72}的最大值索引
代码展示:
public class MaxIndex{ public static void main(String[] args){ int arr[] = {5, 12, 90, 18, 77, 76, 45, 28, 59, 72}; int maxIndex = 0; if(int i = 1;i < arr.length;i++){ if(arr[maxIndex] < arr[i]){ maxIndex = i; } } System.out.println("最大值索引为" + maxIndex); } }
运行截图:
-
获取数组{5, 12, 90, 18, 77, 76, 45, 28, 59, 72}的最小值
代码展示:
public class MinValue{ public static void main(String[] arhs){ int arr[] = {5, 12, 90, 18, 77, 76, 45, 28, 59, 72}; int min = arr[0]; for(int i = 1;i<arr.length;i++){ if(min>arr[i]){ min = arr[i]; } } System.out.println("最小值为 min = " + min); } }
运行截图:
-
获取数组{5, 12, 90, 18, 77, 76, 45, 28, 59, 72}的最小值索引
代码展示:
public class MinIndex{ public static void main(String[] args){ int arr[] = {5,12,90,18,77,76,45,28,59,72}; int minIndex = 0; for(int i = 1 ;i <arr.length;i++){ if(arr[minIndex] > arr[i]){ minIndex = i } } System.out.println("最小值索引minIndex = " + minIndex); } }
运行截图:
-
获取元素59在数组{5, 12, 90, 18, 77, 76, 45, 28, 59, 72}中的第一次出现的索引。
代码展示:
public class FindIndex{ public static void main(String[] args){ int arr = {5, 12, 90, 18, 77, 76, 45, 28, 59, 72}; int value = 59; int index = -1; for(int i = 0;i < arr.length;i++){ if(arr[i] == value){ index = i; break; } } System.out.println("索引为 index = " + index); } }
运行截图:
此文章于11月27日编辑完毕,小编也是个初学者,或许有些内容写的有错误的,我对自己的要求是:有错改之,无错加勉。还望大家能在评论区指点迷津,不胜感激,同时也希望大家口下留情!!