目录
数组
数组也是对象
大纲 | 知识点 |
---|---|
数组的概念 | 数组的定义 |
数组的概念 | 数组的四个特点 |
数组的常见操作 | 普通遍历 |
数组的常见操作 | for-each遍历 |
数组的常见操作 | 数组的拷贝 |
数组的常见操作 | java.util.Array类用法 |
多维数组 | 内存结构 |
多维数组 | 存储表格 |
多维数组 | Javabean和数组存储表格 |
常见算法 | 冒泡排序基础算法 |
常见算法 | 冒泡排序优化算法 |
常见算法 | 二分法查找(折半查找) |
定义
数组是相同类型数据的有序集合。其中,每一个数据称作一个元素,每一个元素可以通过一个索引(下标--index)来访问。(下标从0开始计)
四个基本特点
-
长度是确定的,数组一旦被创建,它的大小是不可改变的
-
其元素类型必须是相同类型,不能出现混合类型
-
数组类型可以是任何数据类型,包括基本类型和引用类型
-
数组变量属于引用类型,数组也是对象,数组中的元素相当于对象的属性
创建数组
声明方式
type[] arr_name; // 方式一
typr arr_name[]; // 方式二
注意事项
-
声明的时候并没有实例化任何对象,只有在实例化数组对象时,JVM才分配空间,这时才与长度有关
-
构造一个数组,必须指定长度
-
声明一个数组时数组并没有真正的被创建
示例-基本类型
package ArraryLearn; public class ArrayCreate { public static void main(String[] args) { int[] s; // 声明数组 s = new int[10]; // 给数组分配空间 System.out.println(s[0]); // 0 System.out.println(s[1]); // 0 s[2] = 20; System.out.println(s[2]); // 20 for(int i = 0;i < 10;i++){ s[i] = 2 * i + 1; System.out.println(s[i]); // 1 3 5 7 9 11 13 15 17 19 } } }
示例-引用类型
package ArraryLearn; public class ArraryCreate01 { public static void main(String[] args) { Man[] mans; // 声明数组 mans = new Man[10]; Man m1 = new Man(18,"张三"); Man m2 = new Man(22,"李四"); mans[0] = m1; mans[1] = m2; System.out.println(mans[0].getAge()); System.out.println(mans[1].getName()); } } class Man{ private int age; private String name; public Man(int age,String name){ this.age = age; this.name = name; } public int getAge() { return age; } public String getName() { return name; } public void setAge(int age) { this.age = age; } public void setName(String name) { this.name = name; } }
初始化
静态初始化
除了用new关键字产生数组意外,还可以直接在定义数组时就为数组元素分配空间并赋值
示例
package ArraryLearn; public class StaticCreateArray { public static void main(String[] args) { // 基本数据类型 int[] a = {1,2,3,4,5,6}; System.out.println(a[1]); // 2 System.out.println(a[0]); // 1 // 引用类型 Man[] mans = {new Man(18,"张三"),new Man(22,"李四")}; System.out.println(mans[1].getName()); // 李四 } }
动态初始化
示例
见示例-及基本类型、示例-引用类型
默认初始化
-
数组是对象,他的元素相当于对象的属性
-
每个元素也按照属性的方法被默认初始化
示例
int i[] = new int[2]; // 默认值:0,0 boolean[] b = new boolean[2]; // 默认值:false,true String[] s = new String[2]; // 默认值:null,null
常见操作
遍历
"通过循环遍历数组的所有元素"
数组元素下标的合法区间:[0,length-1]。可通过下标遍历数组中的元素,遍历时可读取/修改元素的值
示例 for循环
package ArraryLearn; public class BianliArray { public static void main(String[] args) { int[] i = new int[5]; for(int j = 0;j < i.length;j++){ i[j] = 20 * j; System.out.println(i[j]); // 0,20,40,60,80 } } }
示例 for-each循环
专门用于读取数组或集合中的元素,即进行数组遍历
package ArraryLearn; public class BianliArray { public static void main(String[] args) { String[] s = {"张三","李四","王五","陈六"}; for(String temp : s){ // temp可随意取名,临时变量 System.out.println(temp); // 张三,李四,王五,陈六 } } }
-
for-each增强for循环在遍历数组过程中不能修改数组中某元素的值
-
for-each仅适用于简单遍历,不涉及有关索引(下标)的操作
拷贝
-
将某个数组的内容拷贝到另一个数组中
-
实际上“容器的扩容”就是数组的拷贝
-
System.arraycopy(object src,int srcpos,object dest,int destpos,int length)
该方法可以将src数组里的元素值赋给dest数组的元素,其中srcpos指定从src数组第几个元素开始赋值,length参数指定将src数组的多少个元素赋给dest数组的元素
示例
package ArraryLearn; public class CopyArray { public static void main(String[] args) { int[] a = {1,2,3,4,5,6,7,8,9,10}; int[] b = new int[10]; System.arraycopy(a,2,b,3,6); for(int i = 0;i < b.length;i++){ System.out.print(b[i] + "\t"); // 0 0 0 3 4 5 6 7 8 0 } } }
java.util.Arrays类
Arrays类包含了:排序、查找、填充、打印内容等常见的数组操作
示例一 打印数组元素
package ArraryLearn; import java.util.Arrays; public class Test { public static void main(String[] args) { int[] a = {1,2,3,4,5,6,7,8,9,10}; System.out.println(a); // [I@4554617c System.out.println(Arrays.toString(a)); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] } }
注:此处的Arrays.toString()方法是Arrays类的静态方法,不是前面Object的toString()方法
示例二 对数组元素进行排序
package ArraryLearn; import java.util.Arrays; public class Test { public static void main(String[] args) { int[] b = {5,9,3,7,6,3,2,4,10,56}; Arrays.sort(b); // 排序 System.out.println(Arrays.toString(b)); // [2, 3, 3, 4, 5, 6, 7, 9, 10, 56] } }
示例三 实现二分法的查找
package ArraryLearn; import java.util.Arrays; public class Test { public static void main(String[] args) { int[] c = {56,33,12,17,16,52,25,423,2659}; Arrays.sort(c); // 排序 二分法查找必须先对数组进行排序 // 返回排序后新的索引位置,未找到返回负数 System.out.println(Arrays.toString(c)); // [12, 16, 17, 25, 33, 52, 56, 423, 2659] System.out.println("该元素的索引:" + Arrays.binarySearch(c,17)); // 该元素的索引:2 } }
示例四 使用Arrays类对数组进行填充
package ArraryLearn; import java.util.Arrays; public class Test { public static void main(String[] args) { int[] d = {1,2,3,4,5,6,78,12,66,17,65}; System.out.println(Arrays.toString(d)); // [1, 2, 3, 4, 5, 6, 78, 12, 66, 17, 65] Arrays.fill(d,3,6,100); // 将数组d中3-6索引的元素替换为100 System.out.println(Arrays.toString(d)); // [1, 2, 3, 100, 100, 100, 78, 12, 66, 17, 65] } }
多维数组
可以看成以数组为元素的数组。可有二维、三维、甚至更多。
示例 二维数组的声明
package ArraryLearn; public class TestMultipleArray { public static void main(String[] args) { int [][] a = new int[3][]; // int [][] a1 = new int[][3]; 非法形式,应从低维到高维 a[0] = new int[2]; // a指向的数组的第一位又指向一个数组的第一位和第二位 a[1] = new int[3]; // a指向的数组的第一位又指向一个数组的第一、二、三位 a[2] = new int[5]; // a指向的数组的第一位又指向一个数组的第一、二、三、四、五位 a[0][1] = 20; System.out.println(a[0][1]); // 20 a[1][2] = 30; // System.out.println(a[1][3]); // 因为最长指向3,即是a[2],所以会报错ArrayIndexOutOfBoundsException System.out.println(a[1][2]); // 30 System.out.println(a[2][4]); // 0,因为没有赋值,默认为0 a[2][3] = 70; System.out.println(a[2][3]); // 70 } }
示例 静态初始化
package ArraryLearn; public class TestM01 { public static void main(String[] args) { int[][] b = { {1,33,77}, // b0 {17,56,42}, // b1 {18,19,50,23,66} // b2 }; System.out.println(b[1][2]); // 42 } }
示例 动态初始化
package ArraryLearn; public class TestM02 { public static void main(String[] args) { int[][] c = new int[4][]; // c[0] = {1,2,3,4}; // 错误,未声明类型就初始化 c[0] = new int[]{56,33,17,18,22}; c[1] = new int[]{88,66,99,77,44,33,55}; c[2] = new int[]{12,23,34,45,56,67,78,89}; c[3] = new int[]{123,456,789}; System.out.println(c[0][4]); // 22 System.out.println(c[1][6]); // 55 System.out.println(c[2][5]); // 67 System.out.println(c[3][2]); // 789 System.out.println(Arrays.toString(c[0])); // [56, 33, 17, 18, 22] } }
存储表格数据
package ArraryLearn; import java.util.Arrays; public class PrintArrayClass { public static void main(String[] args) { Object[] a = {"2021-04-06","张三",100," 真厉害!"}; Object[] b = {"2021-04-06","李四",85," 还不错哦!"}; Object[] c = {"2021-04-06","王五",59," 怎么回事小老弟?"}; Object[][] temps = new Object[3][]; temps[0] = a; temps[1] = b; temps[2] = c; System.out.println(Arrays.toString(temps[0])); System.out.println(Arrays.toString(temps[1])); System.out.println(Arrays.toString(temps[2])); // for循环实现 for(int i = 0;i < temps.length;i++){ for(int j = 0;j < temps[i].length;j++){ System.out.print(temps[i][j] + "\t"); } System.out.println(); } } }
示例 使用javabean和一维数组保存表格信息
javabean 是一种特殊的Java类,用于封装数据和方法,使它们能够更容易地在应用程序中使用。
package ArraryLearn; public class TestJavabean { public static void main(String[] args) { person[] p = { new person(18,"张三",1,"哈哈","04-06"), new person(19,"李四",2,"嘿嘿","04-06"), new person(20,"王五",3,"吼吼","04-06") }; // 遍历数组 for(person p1:p){ System.out.println(p1); // 打印的是地址 //ArraryLearn.person@4554617c //ArraryLearn.person@74a14482 //ArraryLearn.person@1540e19d } } } class person{ private int age; private String name; private int id; private String job; private String hiredate; public person(int age, String name, int id, String job, String hiredate) { this.age = age; this.name = name; this.id = id; this.job = job; this.hiredate = hiredate; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getJob() { return job; } public void setJob(String job) { this.job = job; } public String getHiredate() { return hiredate; } public void setHiredate(String hiredate) { this.hiredate = hiredate; } // 重写打印出信息 @Override public String toString() { return "person{" + "age=" + age + ", name='" + name + '\'' + ", id=" + id + ", job='" + job + '\'' + ", hiredate='" + hiredate + '\'' + '}'; } }
Comparable接口
----定义比较策略
Comparable接口只有一个方法:
public int CompareTo(Object obj)
obj为要比较的对象
方法中,将当前对象和obj这个对象进行比较,如果大于返回1,等于返回0,小于返回-1(此处的1可以是正整数,-1也可以是负整数)。compareTo方法的代码也比较固定
示例
import java.util.Arrays; public class Test { public static void main(String[] args) { Man[] mans = { new Man(18,"张三"), new Man(29,"李四"), new Man(20,"王五") }; Arrays.sort(mans); System.out.println(Arrays.toString(mans)); } } class Man implements Comparable{ int age; int id; String name; public Man(int age, String name) { this.age = age; this.name = name; } @Override public String toString(){ return this.name; } public int compareTo(Object o){ Man man = (Man) o; if(this.age < man.age){ return -1; } if(this.age > man.age){ return 1; } return 0; } }
常见算法
算法可视化:visualising data structures and algorithms through animation - VisuAlgo
冒泡排序算法
重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来,这样越大的元素会经由交换慢慢"浮"到数列的顶端。
-
比较相邻的元素。如果第一个比第二个大,就交换他们两个
-
对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会 是最大的数
-
针对所有的元素重复以上的步骤,除了最后一个
-
持续每次对越来越少的元素重复上面的步骤,知道没有任何一对数字需要比较
eg:
初始: 3 1 6 8 9 0 7 4 5 2
第一趟:1 3 6 8 0 7 4 5 2 9
第二趟:1 3 6 0 7 4 5 2 8 9
第三趟:1 3 0 6 4 5 2 7 8 9
第四趟:1 0 3 4 5 2 6 7 8 9
第五趟:0 1 3 4 2 5 6 7 8 9
第六趟:0 1 3 2 4 5 6 7 8 9
第七趟:0 1 2 3 4 5 6 7 8 9
第八趟:0 1 2 3 4 5 6 7 8 9
第九趟:0 1 2 3 4 5 6 7 8 9
第十趟:0 1 2 3 4 5 6 7 8 9
示例 冒泡算法
import java.awt.image.AreaAveragingScaleFilter; import java.util.Arrays; public class TestBubblesort { public static void main(String[] args) { int[] values = {3,1,6,8,9,0,7,4,5,2}; System.out.println("初始顺序:" + Arrays.toString(values)); bubbleSort(values); } public static void bubbleSort(int[] values){ int temp; for(int i = 0;i < values.length;i++){ for(int j = 0;j < values.length - 1 - i;j++){ if(values[j] > values[j + 1]){ temp = values[j]; values[j] = values[j + 1]; values[j + 1] = temp; } } System.out.println((i + 1) + "趟排序:" + Arrays.toString(values)); // 打印结果 // 初始顺序:[3, 1, 6, 8, 9, 0, 7, 4, 5, 2] // 1趟排序:[1, 3, 6, 8, 0, 7, 4, 5, 2, 9] // 2趟排序:[1, 3, 6, 0, 7, 4, 5, 2, 8, 9] // 3趟排序:[1, 3, 0, 6, 4, 5, 2, 7, 8, 9] // 4趟排序:[1, 0, 3, 4, 5, 2, 6, 7, 8, 9] // 5趟排序:[0, 1, 3, 4, 2, 5, 6, 7, 8, 9] // 6趟排序:[0, 1, 3, 2, 4, 5, 6, 7, 8, 9] // 7趟排序:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] // 8趟排序:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] // 9趟排序:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] // 10趟排序:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] } } }
示例 优化算法
-
把整个数列分为两部分:前面是无序数列,后面是有序数列
-
判断每一趟是否发生了数组元素的交换,如果没发生,则说明此时数组已经有序,无需再进行比较,可终止
import javax.swing.plaf.synth.SynthOptionPaneUI; import java.util.Arrays; public class GoodBubbleSort { public static void main(String[] args) { int[] a = {3,1,6,8,9,0,7,4,5,2}; System.out.println("原始序列:" + Arrays.toString(a)); bubbleSort2(a); } public static void bubbleSort2(int[] a){ int temp; for(int i = 0;i < a.length - 1;i++){ boolean flag = true; // 标记数组是否有序了 for(int j = 0;j < a.length - 1 - i;j++){ if(a[j] > a[j + 1]){ temp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp; flag = false; // 发生了交换,表明是无序状态,需要继续比较 } } // 根据标记量的值判断是否有序,有序退出循环,无序反之 if(flag){ break; } System.out.println("第" + (i + 1) + "趟排序:" + Arrays.toString(a)); // 输出结果 // 原始序列:[3, 1, 6, 8, 9, 0, 7, 4, 5, 2] // 第1趟排序:[1, 3, 6, 8, 0, 7, 4, 5, 2, 9] // 第2趟排序:[1, 3, 6, 0, 7, 4, 5, 2, 8, 9] // 第3趟排序:[1, 3, 0, 6, 4, 5, 2, 7, 8, 9] // 第4趟排序:[1, 0, 3, 4, 5, 2, 6, 7, 8, 9] // 第5趟排序:[0, 1, 3, 4, 2, 5, 6, 7, 8, 9] // 第6趟排序:[0, 1, 3, 2, 4, 5, 6, 7, 8, 9] // 第7趟排序:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] } } }
二分法查找
binary Search --- 折半检索
查找之前需要排序
import java.util.Arrays; public class TestBinarySearch { public static void main(String[] args) { int[] arr = {30, 20, 10, 40, 50, 60, 70, 80, 55, 90}; int searchNumber = 50; // 所要找的数 Arrays.sort(arr); System.out.println(Arrays.toString(arr)); System.out.println(searchNumber + "元素的索引:" + binarySearch(arr,searchNumber)); // [10, 20, 30, 40, 50, 55, 60, 70, 80, 90] // 50元素的索引:4 } public static int binarySearch(int[] array, int value) { // low 与 high 区间 int low = 0; int high = array.length - 1; while (low <= high) { int middle = (low + high) / 2; if (value == array[middle]) { return middle; // 返回查询到的索引位置 } if(value > array[middle]){ low = middle + 1; } if(value < array[middle]){ high = middle - 1; } } return -1; // 循环完,说明未找到,返回-1 } }