java_Day03:数组的详解

12 篇文章 0 订阅
1 篇文章 0 订阅

1.数组的概述和特点

1.1 数组的慨念

** 数组概念:数组是一种能够存放相同数据类型**的有序集合。
编程的基本功:
数据结构和算法
数据结构:数组,链表,栈,队列,图,哈希表,二叉树

1.2 数组的创建
1.2.1 动态数组的1创建

语法格式:

元素类型[] 数组名 = new 元素类型[数组长度]; // 建议使用这种
元素类型  数组名[] = new 元素类型[数组长度];

【例题】

public class ArrayDemo {
	public static void main(String[] args) {
		int[] arr = new int[5];// 动态定义,建议使用这种
		String arr3[] = new String[5];// 动态定义,不建议使用,以免混淆
	}
}
1.2 静态数组的创建

语法格式:

语法一:元素类型[] 数组名 = new 元素类型[]{元素1,元素2,元素3,元素4,元素n};
语法二:元素类型[] 数组名 = {元素1,元素2,元素3,元素4,元素n};

**注意:**使用静态方式创建数组,数组长度由元素个数来确定
【例题】

public class ArrayDemo {
	public static void main(String[] args) {
		int[] arr1 = new int[] {1,2,3,4,5};// 静态定义
		int[] arr2 = {1,2,3,4,5};// 静态定义,这种方式不可以作为实参变量来使用
	}
}

两种静态创建的区别:
语法二方式创建出来的数组,不可以作为方法的实参,因为编译系统不识别{}是什么数组。

1.3 数组的基本操作

数组中的元素,可以通过 索引 || 下标来访问,索引从零开始,也就是说其取值范围为:【0,数组长度-1】;如果超出索引范围,则会抛出异常:ArrayIndexOutOfBoundsException
【例题】

public class ArrayDemo02 {
	public static void main(String[] args) {
		// 初始化数组,定义元素长度为5
		int[] arr = new int[5];
		// 给第一个元素赋值
		arr[0] = 11;
		// 给第二个元素赋值
		arr[1] = 22;
		// 给第三个元素赋值
		arr[2] = 33;
		// 给第四个元素赋值
		arr[3] = 44;
		// 给第五个元素赋值
		arr[4] = 55;
		
		// 修改第二个元素的值
		arr[1] = 222;
		for (int temp : arr) {
			System.out.println(temp);
		}
	}
}

输出:11
222
33
44
55

1.4 数组元素的默认值
整数(byte,short,int,long)默认值为:0
小数(float,double)默认值为:0.0
布尔类型(boolean)默认值为:false
字符类型(char)默认值为:\u0000,也就是一个空格
引用数据类型(String,数组,Object等)默认值为:null
1.4.2 数组常见的属性
length属性(只读属性),获取数组空间的长度

【示例】

int[] arr = {1,2,3,4,5};
System.out.println(arr.length);// 输出5

3.通过普通for循环获取数组元素
int[] arr = {11, 22, 33, 44, 55, 66, 77};
for(int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
技能:for+length属性
4.通过增强for-each循环获取数组元素
语法:for(数据类型 变量名 : 数组|集合) {
// 循环体
}
技能:for-each
优点:语法简洁,相对执行效率较高!
缺点:遍历过程中,无法获得数组|集合索引!
使用场合:如果需要在循环体中修改数组元素的值,建议使用普通for循环。 —> 有索引
【例题】1、 获取10个学生的成绩,然后保存在数组中,最后计算学生的总分和平均分。

public class ArrayTest01 {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		double[] arr = new double[10];
		for (int i = 0; i < arr.length; i++) {
			System.out.println("请您输入第"+(i+1)+"个学生成绩");
			arr[i] = input.nextDouble();
		}
		double sum = 0.0;
		for (double temp : arr) {
			sum += temp;
		}
		System.out.println("成绩之和为:"+ sum);
		System.out.println("成绩的平均值为:"+ sum/arr.length);
	}
}
1.5 JVM 中的堆和栈(重点)

JVM是基于堆栈的虚拟机,堆栈是一种数据结构,是用来存储数据的。对于一个Java程序来说,它的运行就是通过对堆栈的操作来完成的。
【栈内存 stack】
栈内存:用来存放局部变量
特点:
1.栈内存存储特性为:先进后出,后进先出。
2.栈内存是一段连续的内存空间,由系统自动分配,速度快!
3.虚拟机为每一个线程创建一个栈,用于存放该线程执行方法的信息。

【堆内存 heap】
堆内存:用来存储创建好的对象和数组(数组也是对象)
特点:
1.虚拟机中只有一个堆,被所有线程共享。
2.堆是一段不连续的内存空间,分配灵活,但速度慢!

【思考一】

public class ArrayTest02 {
	public static void main(String[] args) {
		int[] arr1 = {1, 2, 3};
		int[] arr2 = arr1;
		arr1 = null;
		System.out.println(arr1[2]); // 输出结果为???
		System.out.println(arr2[2]); // 输出结果为???
	}
}

【思考二】

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

2.数组常见操作

2.1 获取数组的最值

需求:求int[] arr = {134,23,35,46,57,24,13,56,23,44};这个数组最小值的元素并返回最小值和其下标

public class ArrayMin {
	public static void main(String[] args) {
		int[] arr = {134,23,35,46,57,24,13,56,23,44};
		int min = min(arr);
		System.out.println(min);
	}
	
	/**
	 * 求最小值和其索引
	 * @param arr 用来接收数组
	 * @return 返回最小值
	 */
	public static int min(int[] arr) {
		int index = 0;
		int min = arr[0];
		for (int i = 0; i < arr.length; i++) {
			if (arr[i] < min) {
				min = arr[i];
				index = i;
			}
		}
		System.out.println("最小值索引为:"+index);
		return min;
	}
}
2.2 通过值获取索引

需求:在数组里面找value=44的值的下标,int[] arr = {2,3,16,5,6,7,23,44,24,56};

public class ArrayTest01 {
	public static void main(String[] args) {
		/*
		// 方法一:
		int[] arr = {2,3,16,5,6,7,23,44,24,56};
		int value = 44;
		int i = 0;
		// 数组循环遍历
		for (; i < arr.length; i++) {
			// 判断是否跟要找的值相等
			if(arr[i] == value)
			{
				System.out.println(i);
				break;
			}
		}
		// 如果找不到i的值,说明没有执行上面的break
		if(i == arr.length)
		{
			System.out.println(-1);
		}
		*/
		
		//方法二:
		int[] arr = {2,3,16,5,6,7,23,44,24,56};
		int value = 44;
		int index = GetArrayGetValueGetIndex(arr, value);
		System.out.println(index);
		
	}
	/**
	 * 用来查找你需要查找的数在数组元素中的下标
	 * @param arr 用来接收数组
	 * @param value 用来接收你需要找的值
	 * @return 返回你要找的值的下标,否则返回-1
	 */
	public static int GetArrayGetValueGetIndex(int arr[],int value) {
		// 数组循环遍历
		for (int i = 0; i < arr.length; i++) {
			// 判断是否跟要找的值相等
			if(arr[i] == value)
			{
				return i;
			}
		}
		return -1;
	}	
}
2.3 数组反序输出

需求:将数组反序输出, 需求:将数组反序输出,原数组{5, 12, 90, 18, 77, 76, 45, 28, 59, 72},
反序输出后{72,59,28,45,76,77,18, 90,12,5}。

public class ArrayTest02 {
	public static void main(String[] args) {
		int[] arr = {5, 12, 90, 18, 77, 76, 45, 28, 59, 72};
		int [] newArry = reverseOrder1(arr);
		for (int temp1 : newArry) {
			System.out.print(temp1+" ");
		}
		System.out.println();
		System.out.println("-------------------");
		
		for (int temp2 : newArry) {
			System.out.print(temp2+" ");
		}
	}
	
	/**
	 * 方法二:实现倒序输出,不开辟内存空间
	 * @param arr
	 */
	public static void reverseOrder2(int[] arr) {
		int temp;
		for (int i = 0; i < arr.length/2; i++) {
			temp = arr[arr.length-i-1];
			arr[arr.length-i-1] = arr[i];
			arr[i] = temp;
		}
		
	}
	
	/**
	 * 方法一:实现倒序输出,开辟内存空间
	 * @param arr
	 * @return
	 */
	public static int[] reverseOrder1(int[] arr) {
		int[] desArr = new int[arr.length];
		for (int i = 0; i < desArr.length; i++) {
			desArr[arr.length-i-1] = arr[i];
		}
		 return desArr;
	}
}
2.4 数组元素删除

需求:删除数组int[] arr = {22,13,35,24,15};下标为3的值

public class ArrayTest03 {
	public static void main(String[] args) {
		int[] arr = {22,13,35,24,15};
		int index = 3;
		deleteArray(arr, index);
		for (int temp : arr) {
			System.out.println(temp);
		}		
	}
	
	public static void deleteArray(int arr[],int index) {
		for (int i = index; i < arr.length - 1; i++) {
			arr[i] = arr[i+1];
		}
		arr[arr.length-1] = 0;
	}
}
2.4 数组元素的插入

需求:在数组int[] arr = {11,22,33,44,55,66,88,99};中插入一个下标为6,值为77,插入到该数组中。

public class ArrayTest04 {
	public static void main(String[] args) {
		int[] arr = {11,22,33,44,55,66,88,99};
		int value = 77;
		int index = 6;
		int[] newArray = insertValue(arr, value, index);
		for (int temp : newArray) {
			System.out.print(temp+" ");
		}
	}
	public static int[] insertValue(int[] arr,int value,int index) {
		int size = arr.length;
		if(size == arr.length)
		{
			// 证明需要扩容
			int[] arr1 = new int[arr.length+1];
			// 把原数组中的值插入新数组中
			for (int i = 0; i < arr.length; i++) {
				arr1[i] = arr[i];
			}
			// 把新数组首地址给原数组
			arr = arr1;
			// 从后往前挪动
			for (int i = arr.length-2; i >= index; i--) {
				arr[i+1] = arr[i];
				// 抛出异常
				// throw new IndexOutOfBoundsException();
			}		
			//对要插入的数组元素赋值
			arr[index] = value;
		}		
		// 返回一个原数组,为什么??
		return arr;
	}
}
2.6 数组冒泡排序

需求:对一个没排序的数组进行从小到大的排序

public class ArrayTest05 {
	public static void main(String[] args) {
		// 定义一个数组
		int[] arr = {2,5,7,9,10,3,6,8,1,4};
		bubbleSort(arr);
		for (int temp : arr) {
			System.out.println(temp);
		}
	}
	/**
	 * 冒泡方法
	 * @param arr 用来接收数组
	 * 有参无返回值
	 */
	public static void bubbleSort(int[] arr) {
		// 冒泡优化
		boolean flag = true;
		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;
					flag = false;
				}
			}
			if(flag)
			{
				break;
			}
		}	
	}
}
2.7 二分查找法

二分查找法又称折半查找法。
优点:比较次数少,比起传统比较起来查找速度要更快。
缺点:要求待查表为有序列表
需求:在某一个数组里面查找你需要查找元素的(下标|索引)

public class ArrayTest06 {
	public static void main(String[] args) {
		// 定义一个数组
		int[] arr = {1,3,5,7,9,11,13,15,16,18};
		
		int index = binarySearch(arr,9);
		System.out.println(index);
	}
	
	/**
	 * 折半查找法
	 * @param arr 接收一个数组
	 * @param value 接收下标|索引
	 * @return 返回找到的索引,找不到返回-1
	 */
	
	public static int binarySearch(int[] arr,int value) {
		// 定义两个值max,min,用来存放索引最大值和最小值[0,arr.length - 1]
		int max = arr.length - 1;
		int min = 0;
		// 定义一个中间变量
		int mid = 0;
		
		// 由于不知道循环次数,采用死循环
		while(true)
		{
			//更新mid的值
			mid = (max + min) / 2;
			
			//如果你要查找的值比mid的值大
			if(value > arr[mid])
			{
				min = mid + 1;
			}
			
			//如果你要查找的值比mid的值小
			else if(value < arr[mid])
			{
				max = mid - 1;
			}
			
			//如果相等,代表现在这个值就是你要找的值
			else {
				return mid;
			}		
			
			//如果最小值 min > max 最大值,代表该数组没有这个值
			if(min > max)
			{
				return -1;
			}
		}
	}
}

3.Arrays 工具类

Arrays用于操作数组工具类,里面定义了常见操作数组的静态方法。
**注意:**要使用Arrays工具类,必须要导入Arrays工具类

import java.util.Arrays;
3.1 toString方法

返回指定数组内容的字符串表示形式。
【示例】

int[] arr2 = {1,3,5,7,9};
// 调用toString 方法
System.out.println(Arrays.toString(arr2));// 输出[1, 3, 5, 7, 9]

底层源代码实现

	// toString方法的底层代码实现过程
		public static String toString(int[] arr) {
			//1.定义一个字符串,用于保存数组中的元素
			String str = "[";
			// for循环遍历
			for (int i = 0; i < arr.length; i++) {
				//如果到了最后一个数
				if (i == arr.length - 1) {
					str += arr[i]+ "]";
				}
				else {
					str += arr[i]+",";
				}
			}
			return str;
		}
3.2 equals 判断

判断两个数组中的内容是否相同。
底层源代码实现

//equals方法的底层代码实现过程
		public static Boolean equals(int[] arr1,int[] arr2)
		{
			//判断是否在同一个对象里
			if(arr1 == arr2)//同时也判断两个都为空的情况
			{
				return true;
			}
			//判断是否有其中一个为空
			if(arr1 == null || arr2 == null)
			{
				return false;
			}
			// 判断两个数组长度是否相等
			if(arr1.length != arr2.length)
			{
				return false;
			}
			// 判断两个数组里面的元素是否一致
			for (int i = 0; i < arr1.length; i++) {
				if(arr1[i] != arr2[i])
				{
					return false;
				}
			}
			return true;
		}
3.4 copyOf 拷贝数组

拷贝数组中的元素,从第一个元素开始,也就是从索引0开始拷贝,拷贝元素个数为newLength个。
范围:[0, newLength)
参数一(original):被拷贝的数组。
参数二(newLength):需要拷贝元素的个数,从索引0开始拷贝
返回值:返回拷贝好的数组!

//copyOf 拷贝数组方法底层代码实现
		public static int[] copyOf(int[] original,int newLength) {
			// 定义一个新数组
			int[] newcopy = new int[newLength];
			//循环遍历,把原数组复制到新数组中
			for (int i = 0; i < newLength; i++) {
				newcopy[i] = original[i];
			}
			// 返回拷贝完成的数组
			return newcopy;
		}
3.5 copyOfRange 拷贝数组

拷贝数组中的元素,从指定位置开始,到指定位置结束。
范围:[from, to)
参数一(original):被拷贝的数组。
参数二(from):从哪里开始拷贝(包含)
参数三(to):拷贝到哪里结束(不包含)
返回值:返回拷贝好的数组!

	// copyOfRange 拷贝数组方法底层代码实现
		public static int[] copyOfRange(int[] original, int from, int to) {
			// 判断是否合法
			if(to < from || to < 0 || from < 0 || to >= original.length)
			{
				System.out.println("传入的to或from不合法");
				throw new RuntimeException();
			}
			int[] newcopy = new int[to - from];
			for (int i = from,j = 0; i < newcopy.length; i++,j++) {
				newcopy[i] = original[j];
			}
			
			return newcopy;
		}
3.6.讲解System类中的arraycopy方法
public static native void arraycopy(Object src,  int  srcPos,Object dest,int destPos, int length);
  •   作用:就是用于实现数组元素的拷贝工作。
    
  •   建议:如果需要实现对数组元素的拷贝工作,建议使用System类中的arraycopy方法,而不要去用Arrays工具类中的copyOf()和copyOfRange()方法
    
  •  方法参数分析:
    
  •  src:需要被拷贝的数组(源数组)
    
  •  srcPos:从源数组中的那个位置开始拷贝,传递是一个索引值
    
  •  dest:目标数组,也就是把拷贝的元素放入目标数组中
    
  •  destPos:把拷贝的元素放在目标数组中的哪个位置,传递是一个索引值
    
  •  length:拷贝数组的元素个数		
    
  • 6.native关键字介绍
  •  使用关键字“native”修饰的方法,我们称之为本地方法。
    
  •  本地方法特点:只有方法的声明,没有方法的实现(没有方法体)。
    
  •  为什么会有本地方法的出现呢???
    
  •  	java虽然很强大,但是也有局限性。java不能直接操作硬件!
    
  •  	java中提供的本地方法,本质上就是通过本地方法来调用别的语言(例如:C语言)来操作硬件。	 	 	
    
4.1方法的可变参数

可变参数:适用于参数个数不确定,但类型确定的情况,java把可变参数当做数组处理。
我们使用…表示可变长参数,…位于变量类型和变量名之间,前后有无空格都可以。
*需求:求多个整数之和
*前提:至少有两个及以上整数

public class VariableArrays {
	public static void main(String[] args) {
	
		int sum = add(1,2,5,6,7,34,45,666);
		System.out.println(sum);
		
		
		// int num1 = 1,num2 = 2;
		//	int sum = add(num1, num2, new int[] {1,2,3,4});
		//	System.out.println(sum);
	}
	/**
	 * 多个整数之和
	 * @param num1
	 * @param num2
	 * @param arr
	 * @return 返回所有整数之和
	 */
	
	public static int add(int num1,int num2,int ... arr) {
		int sum = 0;
		sum = num1 + num2;
		for (int temp : arr) {
			sum += temp;
		}
		return sum;
	}
	
	/**
	 * 多个整数之和
	 * @param num1
	 * @param num2
	 * @param arr
	 * @return 返回所有整数之和
	 */
	/*
	public static int add(int num1,int num2,int[] arr) {
		int sum = 0;
		sum = num1 + num2;
		for (int i = 0; i < arr.length; i++) {
			sum += arr[i];
		}
		return sum;
	}
	*/
}
4.2 main 方法的形参

参数String[ ] args的作用就是可以在main方法运行前将参数传入main方法中。

public static void main(String[] args) {
	System.out.println("args数组长度:" + args.length);
	// 遍历args中的每一个元素
	for(String arg : args) {
		System.out.println(arg);
	}
}

5. 二维数组

5.1 二维数组的定义

二维数组本质上是以数组作为数组元素的数组,即“数组的数组”。(通俗来讲二维数组的每一个元素又是一个一维数组)

5.2 二维数组的创建

 创建格式一,创建等长的二维数组
语法语法:数据类型[][] 数组名 = new 数据类型[m][n];
m: 表示这个二维数组的长度。
n: 表示二维数组中每个元素的长度
 创建格式二,创建不定长二维数组
语法格式:数据类型[][] 数组名 = new 数据类型[m][];
m: 表示这个二维数组的长度。
二维数组中元素的长度没有给出,可以动态的给。
 创建格式三,创建静态二维维数组
基本格式:
【示例】
1、 有三个班级,第一个班级3个学生,第二个班级4个学生,第三个班级5个学生。要求通过键盘录入三个班级学生的成绩,并计算每个班级学生的的平均成绩和三个班级学生的总均成绩。

public class DoubleArrayDemo02 {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		double[][] arr = new double[3][];
		
		arr[0] = new double[3];
		arr[1] = new double[4];
		arr[2] = new double[5];
		
		for (int i = 0; i < arr.length; i++) {
			double sum = 0,avg = 0;
			for (int j = 0; j < arr[i].length; j++) {
				System.out.println("请输入第"+(i+1)+"个班"+"第"+(j+1)+"个学生");
				arr[i][j] = input.nextDouble();
				sum  += arr[i][j];
				avg  += arr[i][j];
			}
			System.out.println("第"+(i+1)+"个班的总成绩为:"+sum);
			System.out.println("第"+(i+1)+"个班的平均成绩为:"+avg/arr[i].length);
		}
		
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值