学习目标:
1. jvm内存图入门2. 一维数组的使用3. 二维数组的使用4. 数组的内存结构5. 数组中常见算法6. 数组中常见的异常
java程序运行在jvm上,jvm内存主要分为五块,结构如下:
每块内存负责的职责如下:
局部变量和引用地址都是在栈内存中。
堆:此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。这一点在Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配。
方法区:用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。方法区存放的数据只有一份
本地方法栈(Native Method Stack):与Java虚拟机栈作用很相似,它们的区别在于虚拟机栈为虚拟机执行Java方法(即字节码)服务,而本地方法栈则为虚拟机使用到的Native方法服务。例如调用本地c/c++的方法。
程序计数器:程序计数器是记录当前线程所执行的指令行数。
为什么要有数组?在开发中,我们常常需要存取很多相同类型的数据,用变量的方式需要定义很多变量,不方便管理。所以引入数组的概念,一次存取多个相同类型的数据。数组有两个一定,一个类型一定,一个是大小一定。
数组中存在着一些重要的概念,如下所示:
一维数组的定义语法如下:
示例:
/*** 数组定义*/public class ArrayDemo1 {public static void main(String[] args) {//定义数组int[] arr1;String [] arr2;}}
数组动态初始化语法:
示例:
/*** 数组定义,以及动态初始化*/public class ArrayDemo1 {public static void main(String[] args) {//定义数组int[] arr1;//数组动态初始化arr1 = new int[4];arr1[0] = 10;arr1[1] = 20;arr1[2] = 30;arr1[3] = 40;//取值System.out.println(arr1[0]);System.out.println(arr1[1]);System.out.println(arr1[2]);System.out.println(arr1[3]);}}
数组静态初始化语法:
示例:
/*数组的定义与静态初始化*/public class ArrayDemo2 {public static void main(String[] args) {//数组的声明// String[] arr = new String[]{"乔峰","段誉","杨过"};//简写String[] arr = {"乔峰","段誉","杨过"};//取值System.out.println(arr[0]);System.out.println(arr[1]);System.out.println(arr[2]);}}
引用数组元素内容需要注意以下几点:
示例1:数组元素的引用
/*** 数组元素的引用*/public class ArrayDemo3 {public static void main(String[] args) {//数组的定义int[] arr = {1,3,5,7,9};//查看数组的长度System.out.println(arr.length);// 查看数组内容System.out.println(arr[0]);System.out.println(arr[1]);System.out.println(arr[2]);System.out.println(arr[3]);System.out.println(arr[4]);// 数组下标超过最大下标会越界,报异常ArrayIndexOutOfBoundsExceptionSystem.out.println(arr[5]);}}
示例2:数组的循环赋值与取值
/*** 数组的循环赋值与取值*/public class ArrayDemo4 {public static void main(String[] args) {//定义数组int[] arr = new int[5];//循环赋值for (int i = 0; i < arr.length; i++) {arr[i] = i*5;}//循环取值for (int i = 0; i < arr.length ; i++) {System.out.println(arr[i]);}}}
数组在使用过程中需要注意以下几点:
forEach可以遍历数组或集合容器中的数据,语法如下:
示例:
/*** forEach遍历*/public class ArrayDemo5 {public static void main(String[] args) {//数组定义int[] arr = {1,3,5,7,9};//数组遍历for(int num : arr){System.out.println(num);}}}
当数组元素没有赋值时,是存在默认值的,默认值如下:
将班级所有同学名字录入到一个一维数组中 。
参考答案:
/*** 将班级所有同学名字录入到一个一维数组中*/public class ArrayTest1 {public static void main(String[] args) {//1.创建大小为5的String类型数组String[] names = new String[5];//2.创建扫描仪对象Scanner input = new Scanner(System.in);for(int i=0;i<names.length;i++) {//3.提示信息System.out.println("请输入第"+(i+1)+"个同学名字");//4.接收客户的输入信息String name = input.nextLine();//5.将名字存入数组中names[i] = name;}System.out.println("学生信息如下----------");for(int i=0;i<names.length;i++) {System.out.println(names[i]);}}}
已知一个一维数组如下int[] arr = {1,3,11,5,7,9};求出所有元素的最大值,最小值,和值,平均值,并输出出来。
参考答案:
/*** 已知一个一维数组如下int[] arr = {1,3,11,5,7,9};求出所有元素的最大值,最小值,和值,平均值,并输出出来。*/public class ArrayTest2 {public static void main(String[] args) {//定义数组int[] arr = {1,3,11,5,7,9};//假设0下标是最大值 0下标是最小值int max = arr[0];int min = arr[0];int sum = 0;int avg = 0;//2.判断最大值和最小值for(int i=0;i<arr.length;i++) {if(max<arr[i]) {max = arr[i];}if(min>arr[i]) {min = arr[i];}sum+=arr[i];}avg = sum/arr.length;System.out.println("最大值"+max);System.out.println("最小值"+min);System.out.println("和是"+sum);System.out.println("平均值是"+avg);}}
已知数组int[] arr1 = {1,3,5,7,9} , int[] arr2; 将数组arr1的内容复制到数组arr2中
参考答案:
/*** 已知数组int[] arr1 = {1,3,5,7,9} , int[] arr2; 将数组arr1的内容复制到数组arr2中*/public class ArrayTest3 {public static void main(String[] args) {//1.定义数组int[] arr1,arr2;//2.初始化arr1 = new int[]{1,3,5,7,9};//3.打印数组arr1for(int i=0;i<arr1.length;i++) {System.out.println(arr1[i]);}//4.数组复制操作arr2 = new int[arr1.length];for(int i=0;i<arr1.length;i++) {arr2[i] = arr1[i];}}}
注意:切不可 arr2 = arr1 这不是复制数组内容,这是复制数组内存地址;arr2和arr1会指向同一块堆内存空间,改变arr2的同时也会改变arr1,改变arr1的同时也会改变arr2
已知一个数组如下String[] arr = new String[]{"AA","BB","CC","DD","EE"};,反转arr数组得到如下结果String[] arr = new String[]{"EE","DD","CC","BB","AA"};
参考答案:
/*** 已知一个数组如下String[] arr = new String[]{"AA","BB","CC","DD","EE"};,* 反转arr数组得到如下结果String[] arr = new String[]{"EE","DD","CC","BB","AA"};*/public class ArrayTest4 {public static void main(String[] args) {String[] arr = new String[]{"AA","BB","CC","DD","EE"};for(int i=0;i<arr.length/2;i++) {String str = arr[i];arr[i] = arr[arr.length-i-1];arr[arr.length-i-1] = str;}for(int i=0;i<arr.length;i++) {System.out.println(arr[i]);}}}
如果说可以把一维数组当成几何中的线性图形, 那么二维数组就相当于是一个表格。就像下面图一样:
对于二维数组的理解,我们可以理解为一维数组的数组。既数组0下标是一个一维数组,1下标又是一个一维数组数组...。
二维数组存在两种定义方式,第一种定义方式如下:
int[][]arr = new int[4][3]
; 定义了名为arr的二维数组,二维数组中有4个一维数组 每一个一维数组中有3个元素[0][0]
= 1;示例:
/*** 二维数组动态初始化1*/public class ArrayDemo7 {public static void main(String[] args) {//1.动态定义二维数组方式1/*两种理解方式 y x* 方式1 图形化理解 4 行 3 列 二维数组 int[][] arr = new int[4][3];* 方式2 有 4 个 一维数组 每个一维数组可以存放3个数*/int[][] arr = new int[4][3];//2.获得 4 个一维数组 arr[0] arr[1] arr[2] arr[3]//打印 第0个数组System.out.print(arr[0][0]);System.out.print(arr[0][1]);System.out.println(arr[0][2]);//打印 第1个数组System.out.print(arr[1][0]);System.out.print(arr[1][1]);System.out.println(arr[1][2]);//打印 第2个数组System.out.print(arr[2][0]);System.out.print(arr[2][1]);System.out.println(arr[2][2]);//打印 第3个数组System.out.print(arr[3][0]);System.out.print(arr[3][1]);System.out.println(arr[3][2]);//3.查看二维数组长度System.out.println(arr.length);//4. 查看二维数组0下标长度System.out.println(arr[0].length);//5. 查看二维数组1标长度System.out.println(arr[1].length);//6. 查看二维数组2下标长度System.out.println(arr[2].length);//6. 查看二维数组3下标长度System.out.println(arr[3].length);}}
第二种定义方式如下:
int[][] arr = new int[3][]
; 二维数组中有3个一维数组。 每个一维数组都是默认初始化值null (注意:区别于格式1)注: int[][]arr = new int[][3];
这种写法是错误的
示例:
public class ArrayDemo8 {public static void main(String[] args) {//1.动态初始化2 /*** 图形化理解 定义 4行 图形 几列待定* 定义 4 个 一维数组 一维数组内容 没有初始化 */int[][] arr = new int[4][];//2.定义arr[0] 一维数arr[0] = new int[1];//3.定义arr[1] 一维数arr[1] = new int[2];//4.定义arr[2] 一维数arr[2] = new int[3];//5.定义arr[3] 一维数arr[3] = new int[4];//6.查看 数组长度System.out.println(arr.length);//7.查看0下标数组长度System.out.println(arr[0].length);//8.查看1下标数组长度System.out.println(arr[1].length);//9.查看2下标数组长度System.out.println(arr[2].length);//10.查看3下标数组长度System.out.println(arr[3].length);}}
int[][] arr = new int[][]{{1},{1,2},{1,2,3}};
定义一个名称为arr的二维数组,二维数组中有三个一维数组
每一个一维数组中具体元素也都已初始化 第一个一维数组 arr[0] = {1}; 第二个一维数组 arr[1] = {1,2}; 第三个一维数组 arr[2] = {1,2,3};
以上代码也可以简写为:int[][]
arr = {{1},{1,2},{1,2,3}};
示例:
public class ArrayDemo9 {public static void main(String[] args) {//1.二维数组静态初始化int[][] arr = new int[][] {{1,1,1},{2,2,2},{3,3,3}};//2.简化int[][] arr2 = {{1},{2,2},{3,3,3}};}}
二维数组循环赋值与遍历过程如下
public class ArrayDemo10 {public static void main(String[] args) {//1.矩形int[][] arr1 = new int[4][3];//2.循环赋值for(int y=0;y<arr1.length;y++) {for(int x=0;x<arr1[y].length;x++) {arr1[y][x] = 1;}}//3.循环遍历for(int y=0;y<arr1.length;y++) {for(int x=0;x<arr1[y].length;x++) {System.out.print(arr1[y][x]+"t");}System.out.println();}//2.直角三角形练习String[][] arr2 = new String[4][];//3.循环赋值for(int y=0;y<arr2.length;y++) {//4.定义一维数组arr2[y] = new String[y+1];for(int x=0;x<arr2[y].length;x++) {arr2[y][x] = "*";}}//4.打印二维数组for(int y=0;y<arr2.length;y++) {for(int x=0;x<arr2[y].length;x++) {System.out.print(arr2[y][x]);}System.out.println();}}}
二维数组的动态初始化
二维数组的静态初始化
二维数组的遍历
使用二维数组打印一个10行的杨辉三角
参考答案:
public class ArrayDemo11 {public static void main(String[] args) {//1.定义杨辉三角二维数组int[][] arr = new int[10][];//2.循环初始化 二维数组for(int y=0;y<arr.length;y++) {arr[y] = new int[y+1];//3.给每一行的第一个值和最后一个值赋值为 1arr[y][0] = arr[y][y] = 1;//4.给其他位置赋值//if(y>1) {for(int x=1;x<arr[y].length-1;x++) {arr[y][x] = arr[y-1][x-1]+arr[y-1][x];}//}}//3.遍历for(int y=0;y<arr.length;y++) {for(int x=0;x<arr[y].length;x++) {System.out.print(arr[y][x]+"t");}System.out.println();}}}
已知数组int[] arr = {1,3,5,7,9,11,13};通过二分查找法查找数组中是否包含元素3,如果包含,元素3的下标是多少?注意(只有排好序的数组才能使用二分查找法)
分析过程如下:
另一种情况,当查找元素大于中间元素middle过程如下,这里以查找13为例
参考代码:
/*** 数组元素二分查找法,前提:已排序的数组*/public class BinarySearchArray {public static void main(String[] args) {//定义数组int[] arr = {1,3,5,7,9,11,13};// 定义查找目标数int target = 3;//开始下标int head = 0;//结束下标int end = arr.length-1;//标记是否找到目标元素boolean tag = true;//二分查找while(head<=end){int middle = (head+end)/2;if(arr[middle]==target){System.out.println("查找到元素:"+target+",下标:"+middle);tag = false;break;}else if(arr[middle]>target){end=middle-1;} else {head=middle+1;}}if(tag){System.out.println("没有找到目标元素"+target);}}}
排序:是计算机程序设计中的一项重要操作,是指对数组或集合中的元素进行按照大小或字母排序。
排序的算法有很多很多种,这里以冒泡排序、选择排序、插入排序为例进行讲解。
冒泡排序的设计思想:从0下标开始比较相邻元素,通过交换下标元素位置,把大的元素放后面,小的元素放前面, 比较完一轮完成最后一个元素是最大的,以此类推,经过n轮比较完成排序的过程。
代码实现分析
参考答案
/*** 冒泡排序*/public class SortDemo1 {public static void main(String[] args) {//定义数组int[] arr = {1,11,9,3,7,5};//排序for(int i=0;i<arr.length-1;i++){ //如果有6个数,比较5轮就可以了,剩下一个一定是最小的// 因为是j和j+1比较所以j<arr.length-1,又因为每比较一次,就少比较一个数,// 所以j<arr.length-1-i;for(int j=0;j<arr.length-1-i;j++){// 比较相邻元素,交换相邻下标位置if(arr[j]>arr[j+1]){int t = arr[j];arr[j] = arr[j+1];arr[j+1] = t;}}}//打印数组for(int i=0;i<arr.length;i++){System.out.println(arr[i]);}}}
选择排序的思路是:
代码实现分析
参考答案:
/*** 选择排序*/public class SortDemo2 {public static void main(String[] args) {//定义数组int[] arr = {1,11,9,3,7,5};//选择排序for(int i=0;i<arr.length-1;i++){ //如果6个数,比较5轮即可,剩下最后一个一定是最大的//让0下标i和后面所有下标比较;所以开始是i+1 结束到最大下标for(int j=i+1;j<arr.length;j++){if(arr[i]>arr[j]){int t = arr[i];arr[i] = arr[j];arr[j] = t;}}}//打印数组for(int i=0;i<arr.length;i++){System.out.println(arr[i]);}}}
插入排序的设计思路是:
参考答案:
/*** 插入排序*/public class SortDemo3 {public static void main(String[] args) {//定义数组int[] arr = {1,11,9,3,7,5};//插入排序for(int index = 1;index<arr.length;index++){int t = arr[index];int leftIndex = index-1;while(leftIndex>=0 && arr[leftIndex]>t){arr[leftIndex+1] = arr[leftIndex];leftIndex--;}arr[leftIndex+1] = t;}//打印数组for(int i=0;i<arr.length;i++){System.out.println(arr[i]);}}}
二分查找
冒泡排序
选择排序
插入排序
数组中的常见异常:
一维数组的使用
二维数组的使用
一维数组的常见算法:查找和排序。
原文出处:day04_数组