(一)、数组
(1)、概述
数组:是引用数据类型(类,数组,接口)
数组是底层的数据结构,几乎任何语言都有,数组被分为索引数组和关联数组,目前只涉及索引数组
(2)、数据结构
定义:数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。数据结构往往同高效的检索算法和索引技术有关。
数组
栈
链表
散列
二叉树/红黑树
(3)、应用场景
数组用来储存多个数据,比如单个成绩可以用一个变量储存,那么多个呢?写多个变量不太合适
可以使用数组,来存储多个数据即可,这样一个变量就可以搞定,方便统一操作,但是 数组中元素(数据中的数据)的类型必须一致
int i = 2;
int[] is = {1,2,3,5,57,2}
(4)、数组特性
数组特性 可以看做是一个多个相同数据的一个存储容器,可以对这些数据进行统一管理 是一种引用数据类型 意味着
数组占用两块空间,栈内存变量保存堆内存对象的引用 是一种线性数据结构,内存空间是连续的,类似于单元楼
数据可以保存任意数据的元素,但是每一维的元素类型必须一致 数组的长度不能直接更改,也就意味着 数组一旦确定,不能添加或减少,
除非新建一个新的数组,然后把原数组中的元素复制进去,在复制的过程中,可以进行添加和删除操作 数组中有一个length属性,保存数组的长度
并且数组中元素都有一个独一无二的编号(下标) 要查找数组中某个元素的时候,只需要使用对应的索引下标即可,0 就是第一个元素,1就是第二个,以此类推
这种通过内存地址直寻法,效率极高
操作 : 增删改查 结合数组特性,数组 查找和更改效率极高 , 添加和删除 效率较低
与数组对比 , 还有一个链表, 添加删除效率高,查询更改效率低
(5)、数组声明
数组声明:
静态声明 : 在知道数组中每个元素的值的时候,使用静态声明的方式
数据类型[] 变量 = {值,值,值.....};
int i = 5;
int[] is = {1,2,3,4,5,6}; int[][] is2 = { {1,2,3,4,5,6}, {1,2,3,4,5,6},
{1,2,3,4,5,6}, {1,2,3,4,5,6}.......};
静态声明2:
/**
* 数组传递,第三种声明方式 静态声明
*
* 数据类型[] 变量 = new 数据类型[]{值,值,值};
*
*/
public class Array_06 {
public static void main(String[] args) {
int[] arr = { 1, 2, 3 };
int i = 123;
System.out.println(i);
System.out.println(123);
m1(arr);
// 数组字面量传递
m1(new int[] { 1, 2, 3 });
}
public static void m1(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
动态声明 : 在预先不知道每个元素值是多少的时候,使用动态声明,需要提前指定数组空间长度,并使用默认值占位
整数 : 0
浮点 : 0.0
char :\u0000
boolean : false
引用类型 : null
数据类型[] 变量 = new 数据类型[长度];
int[] is = new
int[10];
(6)、基本操作
①、获取数据(查)与设置数据(改)
public class Array_01 {
public static void main(String[] args) {
int i = 5;
int[] is = { 1, 2, 3, 4, 5, 6, 87, 2, 1, 4 };
int[][] is2 = { { 1, 2, 3, 4, 5, 6 }, { 1, 2, 3, 4, 5, 6 },
{ 1, 2, 3, 4, 5, 6 }, { 1, 2, 3, 4, 5, 6 } };
System.out.println(i);
System.out.println(is);
// 自动类型转换
double[] scores = { 1, 3.4, 'x' };
long[] xx = { 2, 3, 4, 5, 6 };
// 长度
System.out.println(is.length);
// 首元素 索引/下标 index
// 数组对象(数组变量) [ 下标 ]
System.out.println(is[0]);
// 尾元素
System.out.println(is[is.length - 1]);
// 更改操作
// 数组[下标] = 值;
is[1] = 1;
}
}
②、遍历
/**
* 遍历操作
*
* for 和 foreach
*
*/
public class Array_03 {
public static void main(String[] args) {
int[] arr = new int[10];
arr[0] = 100;
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
// 增强for循环
// 把 arr数组中的元素 依次取出 并赋值给 i
for (int i : arr) {
System.out.println(i);
}
}
}
③、常见异常
/**
* 常见异常 1 下标越界异常 java.lang.ArrayIndexOutofBoundsException
* 比如数组中就三个元素,最后一个下标是2,你来5或者来个负数 就凉了
*
* 2 空指针异常 java.lang.NullPointerException 使用null值,访问属性,因为是null,所以压根没有堆内存数组空间
* 所以是找不到数组对象的,自然就没有办法操作数组
*
* null 是卡都没有,堆内存对象都没有 null 和 长度为0 是两个概念
*
*
*/
public class Array_02 {
public static void main(String[] args) {
int[] arr1 = { 1, 2 };
// java.lang.ArrayIndexOutOfBoundsException: 2
System.out.println(arr1[2]);
int[] arr2 = null;
// java.lang.NullPointerException
System.out.println(arr2[0]);
}
}
④数组传递
/**
* 传值和传引用 传值 : 基本 类型传递 引用 : 引用 类型传递
*
*/
public class Array_07 {
public static void main(String[] args) {
int i = 10;
m1(i);
System.out.println(i);
System.out.println("-----");
int[] arr = { 1, 2, 3, 4, 5 };
m2(arr);
System.out.println("-----");
for (int j = 0; j < arr.length; j++) {
System.out.println(arr[j]);
}
}
public static void m1(int i) {
i = 20;
System.out.println(i);
}
public static void m2(int[] i) {
i[0] = 20;
for (int j = 0; j < i.length; j++) {
System.out.println(i[j]);
}
}
}
⑤、数组复制
(①)、实现
/**
* 需求 : 把a数组中的某些数据 复制到 b数组中,并替换指定数据
*
* a = {1,2,3,4,5,6};
*
* b = {11,12,13,14,15,16};
*
* 复制操作
*
* b = {11,2,3,4,15,16};
*
* a,1,b,1,3
*
*/
public class Array_08 {
public static void main(String[] args) {
int[] src = { 1, 2, 3, 4, 5, 6 };
int[] dest = { 11, 12, 13, 14, 15, 16 };
arrayCopy(src, 1, dest, 2, 3);
for (int i = 0; i < dest.length; i++) {
System.out.println(dest[i]);
}
}
/**
* 数组替换式复制
*
* @param src
* 源数组
* @param srcPos
* 源数组起始位置(包含)
* @param dest
* 目标数组
* @param destPos
* 目标数组起始位置(包含)
* @param length
* 复制个数
*
* 因为传引用,并且也没有更改dest的长度,所以不需要返回值
*/
public static void arrayCopy(int[] src, int srcPos, int[] dest,
int destPos, int length) {
for (int i = 0; i < length; i++) {
dest[destPos++] = src[srcPos++];
}
}
}
(②)、API
并不是什么功能都需要自己去编写实现,
很多常用的功能,都已经写好了,直接调用即可
比如我们刚才编写的数组替换复制
package Note;
public class Array_08 {
public static void main(String[] args) {
int[] src = { 1, 2, 3, 4, 5, 6 };
int[] dest = { 11, 12, 13, 14, 15, 16 };
// 源数组,起始索引(包含),目标数组,起始索引(包含) , 复制个数
System.arraycopy(src, 1, dest, 2, 3);
for (int i = 0; i < dest.length; i++) {
System.out.println(dest[i]);
}
}
}
(③)、插入式复制
/**
* 模拟插入式复制
*
* 插入式复制,肯定需要更改长度大小,所以只能新建数组
*
* 所以 需要把新数组返回
*
* 1 新数组长度
*
* 2 复制逻辑 1 目标数组 起始位置和之前的数据 先复制到新数组中 2 把源数组起始位置开始 复制length个,到新数组中 3 目标数组
* 起始位置之后的数据 复制到新数组中
*
* 3 返回新数组
*
*/
public class Third {
public static void main(String[] args) {
int c = 4;
int[] src = { 1, 23, 3, 5, 9, 6 };
int[] end = { 4, 6, 3, 7, 2, 7, 1, 6, 7 };
int[] a = new int[9 + c];
// 把end数组 导入位置前的数据导入新数组a
System.arraycopy(end, 0, a, 0, 5);
// 把数组中被导入数据 导入新数组a
System.arraycopy(src, 2, a, 5, c);
// 把end数组 导入位置后的数据导入新数组a
System.arraycopy(end, 5, a, 5 + c, 4);
for (int b : a) {
System.out.print(b + " ");
}
}
}
(7)、二维数组
① 、声明方式与使用方式
/**
* 二维数组 可以模拟平面表
*
*/
public class Array_10 {
public static void main(String[] args) {
// 静态声明二维数组
int[][] arr = { { 1, 2, 3 }, { 11, 12, 13 }, { 0 },
{ 10, 21, 11, 34, 99 } };
System.out.println(arr.length);
// 获取第一个一维数组
int[] arr0 = arr[0];
int arr00 = arr0[0];
System.out.println(arr00);
// 第一个数组中的第一个元素
System.out.println(arr[0][0]);
// 最后一个数组中最后一个元素
System.out.println(arr[3][4]);
int[] arr3 = arr[arr.length - 1];
int arr34 = arr3[arr3.length - 1];
System.out.println(arr[arr.length - 1][arr[arr.length - 1].length - 1]);
// 遍历二维数组
for (int i = 0; i < arr.length; i++) {
// int[] arri = arr[i];
for (int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
}
/**
* 二维数组动态声明
*
* int[][] arr = new int[5][3]; 二维数组中 有5个一维数组,并且每个一维数组中有3个元素
*
* int[][] arr = new int[5][]; 二维数组中有5个一维数组,并且每个一维数组都是空的 需要单独对每个一维数组进行设置
*
*/
public class Array_11 {
public static void main(String[] args) {
int[][] arr = new int[5][3];
arr[2][2] = 1;
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
int[][] arr1 = new int[5][];
// 初始化一维数组
for (int i = 0; i < arr1.length; i++) {
arr1[i] = new int[i + 1];
}
for (int i = 0; i < arr1.length; i++) {
for (int j = 0; j < arr1[i].length; j++) {
System.out.print(arr1[i][j] + " ");
}
System.out.println();
}
}
}
(8)、Scanner
import java.util.Scanner;
/**
* 接收命令行输入
*
*/
public class Array_12_Scanner {
public static void main(String[] args) {
// 接收用户输入
Scanner s = new Scanner(System.in);
// 程序执行到这里,就会进入等待状态,等待用户输入
// 并把输入的数据,返回,并赋值给变量userInput
// 多个数据以空格隔开
// String userInput = s.next();
// System.out.println(userInput+"-------");
// 接收一行数据,不需要分隔符
// String userInput = s.nextLine();
// System.out.println(userInput);
// 接收整型,必须是纯数字,小数点也不行 java.util.InputMismatchException
// int userInput = s.nextInt();
// System.out.println(userInput);
// 接收小数,可以有一个小数点
double userInput = s.nextDouble();
System.out.println(userInput);
}
}
(9)、排序
① 、交换变量的值
public class Array_14 {
public static void main(String[] args) {
// 1 中间变量(开发常用)
int x = 10;
int y = 20;
int temp = x;
x = y;
y = temp;
System.out.println(x + " : " + y);
// 2 位移运算(面试常用)
// 转换为对应的二进制,然后每位进行异或 , 相同为0 不同为1
// 0010
// 0011
x = 2;
y = 3;
x = x ^ y;
// 0001
// 0011
y = x ^ y;
// 0001
// 0010
x = x ^ y;
// 0011
// 0010
System.out.println(x + " : " + y);
// 3 加减运算
x = 10;
y = 20;
x = x + y;
y = x - y;
x = x - y;
System.out.println(x + " : " + y);
}
}
②、冒泡排序
/**
* 冒泡排序 1 比较相邻的两个元素,如果第一个比第二个大,就交换位置 2 对每一对相邻的元素做 相同的比较工作,这样比较完一轮之后,最后一个元素一定是最大的
* 3 再重复执行上面的步骤,除了最后一个元素(比较次数依次递减) 4 一直到没有任何一对元素,终止
*
* 嵌套循环 1 外层循环决定比较多少轮 2 内存循环决定每轮比较多少次
*
*/
public class Array_15_BubbleSort {
public static void main(String[] args) {
int[] arr = { 1, 5, 4, 2, 3 };
bubbleSort(arr);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
public static void bubbleSort(int[] arr) {
int count = 0;
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {
count++;
if (arr[j] < arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
// 1,5,4,2,3
// 5,4,2,3,1 i=0,j=3
// 5,4,3,2,1 i=1,j=2
// 5,4,3,2,1 i=2,j=1
// 5,4,3,2,1 i=3,j=0
}
System.out.println("执行了 : " + count);
}
}
③、选择排序
/**
* 选择排序
* 1 每次都把当中最小的放到左边
* 先拿出第一个,假设是最小的,然后挨个和后面所有比较,全部比较完之后,就找到了最小的元素,放到前面
*
*/
public class Array_16_SelectSort {
public static void main(String[] args) {
int[] arr = {1,5,4,2,3};
selectSort(arr);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
public static void selectSort(int[] arr){
for (int i = 0; i < arr.length; i++) {
// min 是最小的元素下标,默认假设 i 就是最小的
int min = i;
for (int j = i+1; j < arr.length; j++) {
// 有比min还小的,就把下标赋值给min
if (arr[min] > arr[j]) {
min = j;
}
}
// 1,5,4,2,3 i = 0 , min = 0,i=0 , j=4
// 5,1,4,2,3 i = 0 , min = 0 ,i=1, j=4
// 5,4,1,2,3 i = 0 , min = 1 ,i=2, j=4
// 5,4,2,1,3 i = 0 , min = 2 ,i=3, j=4
// 5,4,2,3,1 i = 0 , min = 3 ,i=4, j=4
// 判断i是否是最小的
// 只要 min 不等于 i 说明 有比i小的
if (min != i) {
int temp = arr[min];
arr[min] = arr[i];
arr[i]=temp;
}
}
}
}
④、API
import java.util.Arrays;
public class Array_17_APISort {
public static void main(String[] args) {
int[] arr = { 1, 5, 4, 2, 3 };
Arrays.sort(arr);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}