Java第二周学习

Java第二周学习

1. 数组

1.1 定义数组格式

数据类型[] 数组名 = new 数据类型[容量];

 int[] arr = new int[10];

赋值左侧

数据类型:
告知编译器,当前数组中能够保存的数据类型到底是什么?并且在确定数据类型之后,整个数组中保存的数据类型无法修改!!!
[]:

  1. 告知编译器这里定义的是一个数组类型数据。

  2. 明确告知编译器,数组名是一个【引用数据类型】

数组名:

  1. 操作数据非常重要的数据!!!

  2. 数组名是一个【引用数据类型】

小拓展: int(*) (void *, void *)

赋值号右侧

new:

	申请【XX】内存空间,并且清空整个内存空间中所有二进制位,所有的二进制

	位都是0

数据类型:

	前后呼应,告知编译器这里支持存储的数据类型到底是什么?

[容量]:

	容量==> Capacity

	告知编译器,当前数组中能够存放的对应数据类型的数据,最大存储多少

	个!!

	【注意】

		一旦确定容量,针对于当前数组,后期容量无法修改

1.2 数组的下标【重点】

规定
数组中的下标是从0开始,到数组的容量 - 1

例如:
数组容量为10
有效下标范围: 0 ~ 9
超出有效下标范围,都是无效下标,后期考虑数组处理异常问题,负数使用问题

操作会出现的问题:
1. 数组下标越界
ArrayIndexOutOfBoundsException

1.3 数组内存分析图

在这里插入图片描述【补充知识点 引用数据类型】
开发中引用数据类型
用于保存其他内存空间的首地址,保存地址之后,CPU可以通过对应的引用数据类型,得到对应的地址,从而访问地址对应内存空间。
引用数据类型包括字符串,数组,对象。就这三个!

获取数组容量的方式
数组名.length 属性
当前数组的属性length是要占用一定的数组空间的,属于数组中的内容,这就是为什么数组中占用的空间要比存储数据计算空间略大一些。

1.4 数组地址转移问题

class Demo3 {
	public static void main(String[] args) {
		int[] arr1 = new int[10];
		int[] arr2 = new int[10];

		arr1[5] = 100;
		arr2[5] = 500;
		
		System.out.println(arr1[5]);
		System.out.println(arr2[5]);
		
		arr1 = arr2;
		arr1[5] = 2000;
		
		System.out.println(arr1[5]);
		System.out.println(arr2[5]);
	}
}

数组地址转移示意图
在这里插入图片描述

1.5 数组在方法中的使用

class Demo4 {
	public static void main(String[] args) {
		int[] array = new int[10];
		
		// 调用赋值数组中元素的方法
		// 调用参数是一个数组类型的方法,需要传入的内容是数组名
		assignIntArray(array);
		printIntArray(array);
	}
	
	/*
	需求:
		赋值一个int类型的数组
	方法分析:
		public static 固定格式 不要问
		返回值类型:
			void 无返回值
		方法名:
			assignIntArray 见名知意,动宾结构,小驼峰命名法
		形式参数列表:
			这里需要的是一个int类型的数组
			(int[] arr)
	方法声明:
		public static void assignIntArray(int[] arr)
	*/
	/**
	* 赋值一个指定的int类型数组
	*
	* @param arr 这里需要的参数是一个int类型数组
	*/
	public static void assignIntArray(int[] arr) {
		for (int i = 0; i < arr.length; i++) {
			arr[i] = i + 1;
		}
	}
	
	/*
	需求
		展示一个int类型数组中保存的数据
	方法分析:
		public static: 不要问
		返回值类型:
			void
		方法名:
			printIntArray
		形式参数列表:
			这里需要展示的是一个int类型数组
			(int[] arr)
	方法声明:
		public static void printIntArray(int[] arr)
	*/
	/**
	* 展示一个int类型数组中保存的数据
	*
	* @param arr 这里需要的是一个int类型数组
	*/
	public static void printIntArray(int[] arr) {
		for (int i = 0; i < arr.length; i++) {
			System.out.println("array[" + i + "]=" + arr[i]);
		}
	}
}

1.6 数组算法

1.6.1 完成一个数组逆序过程

/*
静态数组
	int[] arr = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10};
	逆序完成
		{10, 8, 6, 4, 2, 9, 7, 5, 3, 1};
方法的分析
	public static 不要问
	返回值类型:
		void 不需要返回值
	方法名:
		逆序 reverse
	形式参数列表:
		int[] arr
方法声明:
	public static void reverse(int[] arr)
*/

/**
* 完成对于int类型数组的逆序过程
*
* @param arr int类型数组
*/
public static void reverse(int[] arr) {
    int temp = 0;
    for (int i = 0; i < arr.length / 2; i++) {
        /*
        arr[0] = arr[9]
        arr[1] = arr[8]
        arr[2] = arr[7]
        arr[3] = arr[6]
        arr[4] = arr[5]
        */
        temp = arr[i];
        arr[i] = arr[arr.length - 1 - i];
        arr[arr.length - 1 - i] = temp;
    }
}

1.6.2 找出数组中最大值所在下标位置

class ArrayMethod2 {
	public static void main(String[] args) {
		int[] arr = {1, 3, 5, 7, 19, 2, 4, 19, 8, 10};
		
 		int index = maxIndexOf(arr);
		System.out.println("index:" + index);
	}
	
	/*
	需求
		从int类型数组中找出对应的最大值下标位置
	方法分析:
		public static 不要问
		返回值类型:
			数组的下标数据类型是int类型
			int
		方法名:
			maxIndexOf
		形式参数列表:
			(int[] arr)
	方法声明:
		public static int maxIndexOf(int[] arr)
	*/

	/**
	* 返回指定int类型数组中最大值的下标位置
	*
	* @param arr int类型数组
	* @return 返回值是最大值所在的下标位置
	*/
	public static int maxIndexOf(int[] arr) {
		// 假定下标为0的元素是数组中最大值。
		int maxIndex = 0;
		
		// 因为循环过程中,没有必要假定的下标为0的元素和自己比较
		// 循环变量从1开始
		for (int i = 1; i < arr.length; i++) {
			/*
			如果发现maxIndex保存的下标对应元素,是小于i的
			保存对应的i值
			*/
			if (arr[maxIndex] < arr[i]) {
				maxIndex = i;
			}
		}
		
		return maxIndex;
	}
}

1.6.3 找出数组中指定元素所在的第一次出现下标位置

class ArrayMethod3 {
	public static void main(String[] args) {
		int[] arr = {1, 3, 5, 7, 9, 1, 3, 5, 7, 9};
		
		int index = indexOf(arr, 1);
		if (index >= 0) {
			System.out.println("index : " + index);
		} else {
			System.out.println("Not Found!");
		}
		
	}
	/*
	需求:
		找出数组中指定元素出现的第一次下标位置
		1. 第一次出现的问题
		2. 多个元素问题
		3. 有可能不存在指定元素。
	方法分析:
		public static 不要问
		返回值类型:
			int 因为需要返回下标
			考虑在int范围以内,使用一个明确和正确数据有对立
			关系的数据作为【错误标记】
			找到对应数据 0 ~ array.length -1 
			-1 是一个明确的非法下标
		
		方法名:
			indexOf 找出对应元素所在下标位置
		形式参数列表:
			首先是一个int类型数组
			查询的数据也是int类型
			(int[] arr, int find)
	方法声明:
		public static int indexOf(int[] arr, int find)
	*/
	/**
	* 找出指定数组中,指定元素的下标位置,通过返回值返回
	*
	* @param arr 指定的int类型源数据数组
	* @param find 指定需要查询的数据
	* @return 返回值大于等于0,表示找到对应的数据,否则返回-1
	*/
	public static int indexOf(int[] arr, int find) {
		// 首先假设对应查询的数据是不存在的!!!
		int index = -1;
		
		// 利用循环,从下标为0的元素开始到最大下标,比对是否存在find
		for (int i = 0; i < arr.length; i++) {
			// 发现指定find元素和下标为i的元素一致
			if (find == arr[i]) {
				// 使用index保留对应的下标i
				index = i;
				// 终止循环!!!
				break;
			}
		}
		
		return index;
	}
}

1.6.4 获取数组中指定下标的元素

class ArrayMethod4 {
	public static void main(String[] args) {
		int[] arr = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10};
		
		System.out.println(get(arr, 20));
	}
	
	/*
	需求
		找出指定下标的元素
	方法分析:
		public static 不要问
		返回值类型:
			数组为int类型,这里返回值也是int类型
		方法名:
			get
		形式参数列表
			指定的数组 int[] arr
			指定的下标 int index
			0 ~ arr.length - 1
	方法声明:
		public static int get(int[] arr, int index)
	*/
	/**
	* 找出数组中指定下标的元素
	*
	* @param arr 指定的int类型数组  
	* @param int 指定查询的下标位置
	* @return 返回对应下标位置的元素
	*/
	public static int get(int[] arr, int index) {
		// 用户指定的index不能超出有效下标范围
		if (index < 0 || index > arr.length - 1) {
			/*
			返回任何的数据类型都不合适,可以考虑终止方法,
			并且告知用户错误是什么
			后期课程中可以使用到异常处理
			【用户输入参数合法性判断】
			*/
			System.out.println("Input Parameter is Invalid!");
			// 当前方法退出!!!
			System.exit(0);
		}
		
		return arr[index];
	}
	
}

1.6.5 找出数组中最小值的下标位置

public class Demo1 {
	public static void main(String[] args) {
		int[] arr = {1, 3, 5, 7, 9, 0, 4, 6, 8, 10};
		
		// Ctrl + 1  Assign statement to new local variable
		int min = minIndexOf(arr);
		System.out.println("min index : " + min);
	}
	
	/*
	 * 1.1 找出数组中最小值的下标位置
	 * 
	 * 方法分析:
	 * 		public static 不要问
	 * 		返回值类型:
	 * 			这里需要返回数据是数组的下标
	 * 			int类型
	 *		方法名:
	 *			minIndexOf
	 *		形式参数列表:
	 *			这里需要一个int类型数组
	 *			(int[] arr)
	 * 方法声明:
	 * 		public static int minIndexOf(int[] arr)
	 */
	
	/**
	 * 当前方法是找出指定int类型数组中最小值所在的下标位置
	 * 
	 * @param arr int类型数组
	 * @return 最小值所在的下标位置
	 */
	public static int minIndexOf(int[] arr) {
		// 假设最小值下标位置是下标为0的元素
		int min = 0;
		
		for (int i = 1; i < arr.length; i++) {
			if (arr[min] > arr[i]) {
				min = i;
			}
		}
		
		return min;
	}
}

1.6.6 找出数组中指定元素的最后一次出现的下标位置

public class Demo2 {
	public static void main(String[] args) {
		int[] arr = {1, 3, 5, 7, 9, 1, 3, 5, 7, 9};
		
		int index = lastIndexOf(arr, 7);
		
		System.out.println("last Index Of : " + index);
	}
	
	/*
	 * 1.2 找出数组中指定元素的最后一次出现的下标位置
	 * 方法分析:
	 * 		public static 不要问
	 * 		返回值类型:
	 * 			int 返回值是一个下标
	 * 		方法名:
	 * 			indexOf 第一次出现的位置
	 * 			lastIndexOf 最后一次出现的位置
	 * 		形式参数列表:
	 * 			1. 源数据数组,int类型
	 * 			2. 查询的指定元素 int类型
	 * 			(int[] arr, int find)
	 * 方法声明:
	 * 		public static int lastIndexOf(int[] arr, int find)
	 */
	/**
	 * 找出数组中指定元素最后一次出现的位置
	 * 
	 * @param arr 指定的int类型源数据数组
	 * @param find 指定需要查询的数据
	 * @return 返回值大于等于0表示找到数据,否则返回-1
	 */
	public static int lastIndexOf(int[] arr, int find) {
		// 假设我们找不到对应的数据
		int index = -1;
		
		for (int i = arr.length - 1; i >= 0; i--) {
			// 找到对应元素,保存index,终止循环
			if (find == arr[i]) {
				index = i;
				break;
			}
		}
		
		return index;
	}
}

1.6.7 找出指定元素在指定数组中所有下标位置 【难点】

/*
要求:
	a. 不允许在方法内打印展示
	b. 考虑多个数据情况
	c. 需要在方法外获取到下标数据信息
	d. 不允许使用数组作为返回值
【重点】
	1. 尾插法思想,计数器同时也是下一次存放数据的位置
	2. 数组作为方法参数之后,是可以近似数据传导
*/
/**
 * 【重点】
 * 
 * @author Anonymous
 */
public class Demo3 {
	public static void main(String[] args) {
		int[] arr = {5, 3, 5, 7, 5, 1, 3, 5, 7, 9};
		int[] indexArr = new int[arr.length];
		
		int count = allIndexOf(arr, indexArr, 5);
		
		// count是查询到的指定元素个数,同时可以利用与循环中,找到对应的元素
		for (int i = 0; i < count; i++) {
			System.out.println(indexArr[i]);
		}
		
	}
	
	/*
	 * 1.3. 找出指定元素在指定数组中所有下标位置 【难点】
	 * 要求:
	 * 		a. 不允许在方法内打印展示
	 * 		b. 考虑多个数据情况
	 * 		c. 需要在方法外获取到下标数据信息
	 * 		d. 不允许使用数组作为返回值
	 * 方法分析:
	 * 		public static 不要问
	 * 		返回值类型:
	 * 			int 返回找到的指定元素个数
	 * 			void 不行!!!少用黑盒方法!!!
	 * 			boolean true false 局限性比较大
	 * 		方法名:
	 * 			allIndexOf tips:感谢雄飞同学的友情提示
	 * 			找出所有指定元素的下标位置
	 * 		形式参数列表:
	 * 			1. 查询数据的源数据数组 int[] arr
	 * 			2. 指定查询的元素  int find
	 * 			3. 和源数据数组容量一致的int类型数组,保存对应的下标位置
	 * 			(int[] arr, int[] indexArr, int find)
	 * 问题:
	 * 		1. 查询数据可能是多个!!!
	 * 		2. 数组不能作为返回值!!!
	 * 		3. 不允许打印!!!
	 * 		4. 外部获取!!!
	 * 思考:
	 * 		1. 保存查询数据的下标位置一定会使用到数组
	 * 		2. 保存下标的数组数据类型是int类型
	 * 解决方案:
	 * 		通过方法为参数形式传入一个数组,int类型,保存找到的下标位置
	 * 思考:
	 * 		保存下标的数组容量如果考虑
	 * 解决方案:
	 * 		哪怕源数据数组中所有数据都是指定的元素,最大容量也就是
	 * 		和源数据数组的容量一致【判断的地方!!!】
	 * 
	 * 问题:
	 * 		有没有可能性下标为0的元素就是目标元素???
	 * 		0是有效下标范围
	 * 
	 * 		new创建一个新的数组,int类型数组中,所有的元素初始值都是0
	 * 		任何判断0是有效下标还是无效数据???
	 * 需求:
	 * 		这里需要一个数据,告知我找到数据到底有多少个
	 * 返回值:
	 * 		找到的指定元素的个数,如果没有找到,返回0 
	 * 
	 * 方法声明:
	 * 		public static int allIndexOf(int[] arr, int[] indexArr, int find)
	 *
	 */
	/**
	 * 找到指定源数据数组中所有指定元素所在的下标位置,保存到indexArr中,并且返回值
	 * 是找到的元素个数
	 * 
	 * @param arr 源数据数组,int类型
	 * @param indexArr 找到的下标位置存储数组,要求该数组的容量不得小于源数据容量
	 * @param find 需要查询的指定数据
	 * @return 返回值大于0,找到的数据个数,没有找到返回0
	 */
	public static int allIndexOf(int[] arr, int[] indexArr, int find) {
		// 参数合法性判断
		// 如果存储下标的数组长度小于原数组长度,有可能存储不完数据,
		// 这里就要提醒用户给的数组长度不对
		if (arr.length > indexArr.length) {
			System.out.println("Input Parameter is Invalid!");
			// 参数不合法,没有找到数据
			return 0;
		}
		
		/*
		 * 定义一个变量,
		 * 		1. 计数器,记录找到的元素个数
		 * 		2. 尾插法当中下一次存放元素的位置
		 */
		int count = 0;
		
		// 利用for循环遍历整个源数据arr数组
		for (int i = 0; i < arr.length; i++) {
			// 找到了对应的元素,需要保存下标i
			if (find == arr[i]) {
				// 保存到indexArr数组中
				// 需要使用尾插法!!!保存下一次存放数据的位置
				indexArr[count] = i; 
				// 计数器 += 1 
				count += 1;
			}
		}
		
		return count;
	}
}

1.6.8 在指定位置插入指定元素【难点】

/*
存在一个数组,数组中的元素为
	int[] array = {1, 3, 5, 7, 9, 11, 13, 15, 17, 0};
	要求
		1. 0是无效元素,仅占位使用
		2. 当前数组中【有效元素】个数为9
	需求
		在该数组中的指定下标位置放入指定元素
【重点】
	1. 空数据,无效数据思想
	2. 数据的移动过程,粗加工,细打磨过程
	3. 时间消耗问题
*/

在这里插入图片描述

在这里插入图片描述

public class Demo4 {
	public static void main(String[] args) {
		int[] array = {1, 3, 5, 7, 9, 11, 13, 15, 17, 0};
		
		add(array, 9, 20);
		
		System.out.println(Arrays.toString(array));
	}
	
	/*
	1.4 在指定位置插入指定元素【难点】
	存在一个数组,数组中的元素为
		int[] array = {1, 3, 5, 7, 9, 11, 13, 15, 17, 0};
		要求
			1. 0是无效元素,仅占位使用 ==> null
			2. 当前数组中【有效元素】个数为9
		需求
			在该数组中的指定下标位置放入指定元素
	推演过程:
		    在数组下标为5的位置插入元素,从下标5开始
		之后的元素整体向右移动
		    arr[9] = arr[8];
		    arr[8] = arr[7];
		    arr[7] = arr[6];
		    arr[6] = arr[5];
		    arr[5] = 20;
		指定下标为5的位置添加元素,数组中的元素整体
		向后移动的4次
	
	方法分析:
		public static 不要问
		返回值类型:
			void 可用,但是不建议
			boolean 可以 true false 选择boolean类型
			int 可用 返回值的含义约束较为麻烦
		方法名:
			add 添加操作
		形式参数列表:
			1. 需要插入数据的数组
			2. 指定插入数据的下标位置
			3. 指定插入的数据
			(int[] arr, int index, int insert);
	方法声明:
		public static boolean add(int[] arr, int index, int insert);
		
	 */
	/**
	 * 在指定的数组中,指定位置插入指定元素
	 * 
	 * @param arr 指定的int类型数组
	 * @param index 指定的下标位置,必须在合理的区间范围以内
	 * @param insert 指定插入的元素,int类型
	 * @return 添加成功返回true,否则返回false
	 */
	public static boolean add(int[] arr, int index, int insert) {
		// 参数合法性判断
		if (index < 0 || index > arr.length - 1) {
			System.out.println("Input Parameter is Invalid!");
			// 方法运行失败!!!
			return false;
		}
		
		/*
		 arr[9] = arr[8];
		 arr[8] = arr[7];
		 arr[7] = arr[6];
		 arr[6] = arr[5];
		 arr[i] = arr[i - 1];
		 arr[i + 1] = arr[i];
		 
		 arr[5] = 20;
		 */
		for (int i = arr.length - 1; i > index; i--) {
			arr[i] = arr[i - 1];
		}
		
		arr[index] = insert;
		
		return true;
	}
}

1.6.9 删除数组中的指定下标的元素【难点】

/*
存在一个数组,数组中的元素为
	int[] array = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19};
	要求:
		1. 0是无效元素,仅占位使用
	需求:
		在当前数组中删除指定下标的元素
	例如:
		指定下标5
		结果 {1, 3, 5, 7, 9, 13, 15, 17, 19, 0} 
		0占位!!!
*/

在这里插入图片描述
在这里插入图片描述

package com.qfedu.a_array;

import java.util.Arrays;

public class Demo5 {
	public static void main(String[] args) {
		int[] array = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19};
		remove(array, 9);
		
		System.out.println(Arrays.toString(array));
	}
	/*
	1.5 删除数组中的指定下标的元素【难点】
	存在一个数组,数组中的元素为
		int[] array = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19};
		要求:
			1. 0是无效元素,仅占位使用
		需求:
			在当前数组中删除指定下标的元素
		例如:
			指定下标5
			结果 {1, 3, 5, 7, 9, 13, 15, 17, 19, 0} 
			0占位!!!
	推理过程:
		    从删除位置开始,之后的元素整体向前移动,
		并且需要在数组原本最后一个位置上存放元素0,0
		是无效元素,占位使用
		    arr[3] = arr[4];
		    arr[4] = arr[5];
		    arr[5] = arr[6];
		    arr[6] = arr[7];
		    arr[7] = arr[8];
		    arr[8] = arr[9];
		    arr[i] = arr[i + 1];
		    arr[i - 1] = arr[i];
		    arr[9] = 0;
	方法分析:
		public static 不要问
		返回值类型:
			boolean
		方法名:
			remove
		形式参数列表:
			1. 删除数据的数组
			2. 指定删除数据的下标位置
	方法声明:
		public static boolean remove(int[] arr, int index)
	*/
	/**
	 * 删除数组中指定下标元素的内容
	 * 
	 * @param arr 源数据数组,int类类型
	 * @param index 指定删除的下标位置
	 * @return 删除操作成功返回true,失败返回false
	 */
	public static boolean remove(int[] arr, int index) {
		// 参数合法性判断
		// index < 0 || index >= arr.length
		if (index < 0 || index > arr.length - 1) {
			System.out.println("Input Parameter is Invalid");
			return false;
		}
		
		/*
		    arr[3] = arr[4];
		    arr[4] = arr[5];
		    arr[5] = arr[6];
		    arr[6] = arr[7];
		    arr[7] = arr[8];
		    arr[8] = arr[9];
		    arr[i] = arr[i + 1];
		    从删除位置开始,到数组的最后一个有效元素位置结束
		 */
		for (int i = index; i < arr.length - 1; i++) {
			arr[i] = arr[i + 1];
		}
		
		// 最后一位数据赋值为0,占位,同时告知用户这是一个无效数据
		arr[arr.length - 1] = 0;
		return true;
	}
}

1.6.10 找出数组中最大值元素,放到下标为0的位置

// 找出数组中最大的元素,放到下标为0的位置,下标为0的元素放到最大值元素位置
int[] arr = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 10 };
System.out.println(Arrays.toString(arr));

// 假设最大值的下标位置为0
int index = 0;

// 这里一定可以得到最大值所在的下标位置
for (int i = 1; i < arr.length; i++) {
	if (arr[index] < arr[i]) {
		index = i;
	}
}

// 交换数据
if (index != 0) {
	int temp = arr[0];
	arr[0] = arr[index];
	arr[index] = temp;
}

System.out.println(Arrays.toString(arr));

1.6.11 接上一题,找出数组中剩余元素的最大值,放到下标为1的位置

int index1 = 1;

for (int i = 2; i < arr.length; i++) {
	if (arr[index1] < arr[i]) {
		index1 = i;
	}
}

if (index1 != 1) {
	int temp = arr[1];
	arr[1] = arr[index1];
	arr[index1] = temp;
}

System.out.println(Arrays.toString(arr));

1.6.12 再接上一题,找出数组中剩余元素的最大值,放到下标为2的位置

int index2 = 2;

for (int i = 3; i < arr.length; i++) {
	if (arr[index2] < arr[i]) {
		index2 = i;
	}
}

if (index2 != 2) {
	int temp = arr[2];
	arr[2] = arr[index2];
	arr[index2] = temp;
}

System.out.println(Arrays.toString(arr));

1.6.13 选择排序算法

public class Demo7 {
	public static void main(String[] args) {
		int[] arr = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 10 };
		System.out.println(Arrays.toString(arr));
		
		selectSort(arr);
		
		System.out.println(Arrays.toString(arr));
	}
	
	/*
	 * 选择排序算法
	 * 方法分析:
	 * 		public static 不要问
	 * 		返回值类型:
	 * 			void
	 * 		方法名:
	 * 			selectSort
	 * 		形式参数列表:
	 * 			需要处理一个int类型数据
	 * 			(int[] arr)
	 * 
	 * 方法声明:
	 * 		public static void selectSort(int[] arr)
	 */
	
	/**
	 * 选择排序算法
	 * 
	 * @param arr 需要进行排序的int类型数据
	 */
	public static void selectSort(int[] arr) {
		// 外层循环控制核心算法的循环次数
		for (int i = 0; i < arr.length - 1; i++) {
			// 从index位置开始找寻极值
			int index = i;
			
			for (int j = i + 1; j < arr.length; j++) {
				if (arr[index] > arr[j]) {
					index = j;
				}
			}
			
			if (index != i) {
				int temp = arr[i];
				arr[i] = arr[index];
				arr[index] = temp;
			}
		}
	}
}

1.7 Arrays数组工具类使用

数组的工具类:
提供了数组操作的基本方法
sort(int[] arr);
经过XXX,XXX,XXX三个大牛优化的利用XXX技术完成的快速排序算法

binarySearch(int[] arr, int find);
二分法查询,要求数组是有序的。

toString(任何类型数组);
把数组内容作出一个String类型字符串返回值
{1, 3, 5, 7, 9} ==> [1, 3, 5, 7, 9]

2. Eclipse使用

2.1 Eclipse使用

  1. 解压缩Eclipse.rar

  2. 发送快捷方式到桌面

  3. 选择自定义Workspace

  4. Eclipse开发环境选择

  5. 创建Java Project
    a. 菜单栏 --> New – > Java Project
    b. Package Explorer --> 鼠标右键 --> New – > Java Project

  6. 怎么修改工作目录默认保存的位置
    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
    在这里插入图片描述在这里插入图片描述

3. 面向对象

3.1 Java中定义类的格式

class ClassName {
// 属性描述
// 行为描述
}

要求:
1. ClassName要求符合大驼峰命名法,并且要做到见名知意!!!
2. 属性描述,是用于描述当前类拥有的一些特征,这里可以使用变量
该变量有一个特定的名字【成员变量】 Field
3. 行为描述,是用于描述当前类可以做到一些事情,这里使用方法。
该方法有一个特定的名字【成员方法】Method

3.2 Java中定义类【成员变量】

/**
 * 这里定义的是一个Person类
 * 
 * @author Anonymous
 */
class Person {
	// 属性描述,这里使用成员变量 Field
	// 使用String类型来描述Person类的姓名属性
	String name;
	
	// 使用int类型数据描述Person类的年龄属性
	int age;
	
	// 使用char类型数据描述Person类的性别属性
	char gender;
}

3.3 Java中定义类【成员方法】

// 使用方法描述Perosn类的吃饭行为                            
public void eat(String food) {                   
	System.out.println("吃" + food);              
}                                                
                                                 
// 使用方法描述Person类的睡觉行为                            
public void sleep() {                            
	System.out.println("说出来你可能不行,是床先动的手~~~");    
}                                                
                                                 
// 使用方法描述Person类的打豆豆行为                           
public void daDouDou() {                         
	System.out.println("吃饭,睡觉,打豆豆");             
}                 

/*
特征:
	1. 目前没有使用static关键字
	2. 方法和之前所学方式形式一致,同样拥有三大元素 返回值,方法名和形式参数列表
*/

3.4 类对象使用

3.4.1 Java中创建类对象的形式

/*
new 对象!!!
*/
// 获取一个扫描器的类对象!!!
Scanner sc = new Scanner(System.in);
/*
java.util.Scanner : 
	数据类型,Scanner类型。创建的【变量】是Scanner的类对象,同时也是一个引用
	数据类型
sc : 
	类对象,变量
	Scanner的类对象,sc是对象名

new :
	申请内存的【堆区】空间,并且清理整个空间中的所有数据。
	代码中,只有有new关键字,一定会使用到内存的堆区空间,并且是新的内存空间。
Scanner(System.in) :
	1. 这里是一个方法,因为有小括号
	2. 方法名字和类名一致
	3. 该方法称之为构造方法,Constructor 构造方法

总结:
	类名 对象名 = new 构造方法(所需参数);
*/

// 这里创建了一个Person类对象,对象名person                               
Person person = new Person();                               
System.out.println(person);                                 
/*                                                          
 * com.qfedu.a_object.Person@15db9742                       
 * com.qfedu.a_object 完整的包名                                 
 * Person 数据类型,这里创建的对象是一个Person类对象                      
 * @15db9742 当前类对象在内存空间的中首地址!!!十六进制展示方式           
 */                                                         
                                                            
Person person1 = new Person();                              
System.out.println(person1);                                
/*                                                          
 * com.qfedu.a_object.Person@6d06d69c                       
 * 发现第二个Person类对象 person1空间首地址6d06d69c 和第一个对象不一致     
 * 这里就意味着两个对象的空间首地址不一致,不是同一个对象!!!            
 */    

3.4.2 Java中使用类对象调用成员变量

/*
int[] arr = new int[10];
获取数组的容量:
	arr.length
	获取一个数组中【的】length属性

格式:
	对象名.属性名/成员变量名;
	. ==> 的
	可以操作取值或者赋值操作。
*/

// 通过Person类对象 person调用类内的成员变量                      
// 【赋值】Person类对象 person中对应的成员变量                     
person.name = "骚磊";                                 
person.age = 16;                                    
person.gender = '男';                                
                                                    
// 【取值】展示Person类对象 person中保存的成员变量数据                 
System.out.println("Name:" + person.name);          
System.out.println("Age:" + person.age);            
System.out.println("Gender:" + person.gender);  

3.4.3 Java中使用类对象调用成员方法

/*
得到了一个Scanner类对象sc
Scanner sc = new Scanner(System.in);
使用过以下方法:
	sc.nextInt();
	sc.nextFloat();
	sc.nextLine().charAt(0);

格式:
	类对象.方法名(必要的参数);
	. ==> 的
*/

3.5 类对象内存分析图

在这里插入图片描述

3.6 类对象内存转移问题

在这里插入图片描述

4. 构造方法 Constructor

4.1 Java编译器提供的默认的构造方法

Java编译器如果发现当前class没有显式自定义构造方法,会默认提供一个无参数构造方法给予使用。
如果Java编译器发现在代码中出现了任何一个构造方法,就不会再提供对应的无参数构造方法。

4.2 自定义使用构造方法

构造方法功能:
初始化当前类对象中保存的成员变量数据。
目前创建对象的方式;
new 构造方法(有可能需要的参数);

new:
1. 根据构造方法提供的数据类型申请对应的堆区内存空间。
2. 擦除整个空间中所有的数据。
构造方法:
初始化在当前内存堆区空间的成员变量对应的数据

格式:
public 类名(初始化形式参数列表) {
初始化赋值语句;
}

要求:
1. 无论什么时候一定要留有一个无参数构造方法备用
2. 根据所需情况完成构造方法参数选择
3. 一个class可以有多个构造方法【方法的重载】

5. 方法的重载

在这里插入图片描述
总结:
1. 所有的方法名字都是一致的!!!
2. 所有的方法参数都是不一样的!!!
3. 同一个类内!!!

这就是方法的重载!!!
优点:
1. 简化了开发压力
2. 简化了记忆压力
3. 更快捷的调用方法,同时又满足了不同的情况!!!

规范:
重载情况下,在同一个类内,不可以出现相同方法名和相同参数数据类型的方法!!!

基本原理:
方法名一致的情况下,通过形式参数列表数据类型的不同来选择不同的方法执行。
反射 ==>Constructor Method

6. this关键字

6.1 this关键字特征

class SingleDog {
	public SingleDog() {
		System.out.println("Constructor : " + this);
	}
	
	public void test() {
		System.out.println("Method Called : " + this);
	}
}
/*
 * this关键字特征:
 * this关键字表示调用当前方法的类对象,
 * 或者是当前构造方法中初始化的类对象
 */
public class Demo4 {
	public static void main(String[] args) {
		SingleDog singleDog = new SingleDog();
		
		System.out.println("Instance : " + singleDog);
		singleDog.test();
	}
}

6.2 解决就近原则问题

/**                                          
 * 使用String类型参数和int类型参数初始化类对象成员变量数据          
 *                                           
 * @param name String类型数据 用于初始化name属性        
 * @param age int类型数据 用于初始化age属性             
 */                                          
public Cat(String name, int age) {           
	name = name;                             
	age = age;                               
	System.out.println("带有两个参数的构造方法");       
}                                            
/*
我们期望使用比较直观的参数名方式,告知调用者这里需要的数据到底是什么?
但是会导致【就近原则】问题
	在构造方法中所有的name,age都会被看作是一个局部变量,而不是成员变量
期望:
	可以有一种参数方式告知编译器这里操作的是一个成员变量,而不是一个局部变量!!!
*/

--------------------------修改方式----------------------------------
 /**                                             
 * 使用String类型参数和int类型参数初始化类对象成员变量数据             
 *                                              
 * @param name String类型数据 用于初始化name属性           
 * @param age int类型数据 用于初始化age属性                
 */                                             
public Cat(String name, int age) {              
	/*                                          
	 * 使用this关键字明确告知编译器这里使用的是一个成员变量,而不是         
	 * 局部变量,解决就近原则问题                            
	 */                                         
	this.name = name;                           
	this.age = age;                                       
}             

成员变量和局部变量的对比

区别 成员变量 局部变量
作用 属性描述,描述当前类拥有哪些属性 在方法运行的过程中保存必要的数据
位置 成员变量定义在class大括号以内,其他大括号之外 在方法大括号或者代码块大括号以内
初始值 成员变量在没有被构造方法赋值的情况下,是对应数据类型的"零"值 未赋值不能参与除赋值之外的其他运算。
作用域 成员变量存储于类对象中,在内存的堆区,哪里持有当前类对象的空间首地址,作用域就在哪里 有且只在当前大括号以内
生存期 成员变量的生存期是随着类对象的创建而开始,当对象被JVM的GC销毁时,成员变量的生存期终止 从定义位置开始,到当前大括号结束

7. 【补充知识点 "零"值】

new关键字申请内存空间,并且擦除的一干二净
对应每一个数据类型的"零"值
基本数据类型
byte short int 0
long 0L
float 0.0F
double 0.0
char ‘\0’ ==> nul
boolean false
引用数据类型
全部为null
Person person null
String str null
int[] arr null

null
是内存地址中非常特殊的东西!!!

8. 【补充知识点 JVM的GC机制 简述】

在这里插入图片描述
Java中内存管理制度GC就类似于图书管理员身份
1. 在单位时间内,检查当前Java程序使用的内存中是否存在无主内存。
2. 标记无主内存,多次标记的情况下,会将无主内存释放,归还内存空间。
好处:
1. 让程序员管理内存更加方便。
2. 内存管理是完全自动化
劣势:
1. 内存回收效率不高。
2. 内存管理出现泄漏问题。

9. 二分法查找

特征:
1. 要求查询的数组必须是一个经过排序之后的数组
2. 多个指定数据的情况下,无法告知到底是第几个数据出现
3. 没有找到数据返回负数
演示:
1 3 5 7 9 11 13 15 17 19
例如:
查询元素 13的下标位置
第一步:
中间下标元素是 下标为4 元素值=9
最小下标为0
最大下标为9
9 < 13
需要修改最小下标 ==> 中间下标 + 1 ==> 5
第二步:
中间下标元素是 下标为7 元素值=15
最小下标为5
最大下标为9
15 > 13
需要修改最大下标 ==> 中间下标 - 1 ==> 6
第三步:
中间下标元素是 下标为5 元素值=11
最小下标为5
最大下标为6
11 < 13
需要修改最小下标 ==> 中间下标 + 1 ==> 6
第四步:
得到结果

/**                                                        
 * 二分法查找算法                                                 
 *                                                         
 * @param sortedArray 这里要求是一个int类型数组,并且是进过排序之后的升序数组        
 * @param find 需要查询的元素                                     
 * @return 返回值大于等于0找到元素下标位置,没有找返回-1                        
 */                                                        
public static int halfSearch(int[] sortedArray, int find) {
	int minIndex = 0;                                      
	int maxIndex = sortedArray.length - 1;                 
	int mid = (minIndex + maxIndex) / 2;                   
	                                                       
	while (minIndex <= maxIndex) {                         
		if (sortedArray[mid] > find) {                     
			maxIndex = mid - 1;                            
		} else if (sortedArray[mid] < find) {              
			minIndex = mid + 1;                            
		} else {                                           
			return mid;                                    
		}                                                  
		                                                   
		mid = (minIndex + maxIndex) / 2;                   
	}                                                      
	                                                       
	return -1;                                             
}        

10. 面向对象的三大特征之封装

10.1 不局限于面对对象的封装

方法的封装
工具类的封装
框架的封装

需要拥有封装的思想!!!可以用于整合的知识点!!!

10.2 符合JavaBean规范的类封装过程

代码规范非常重要
后期可以有效的提供我们的开发效率!!!

在Java中定义符合JavaBean规范的类有什么要求
1. 所有的成员变量全部私有化 ==> private
2. 必须提供一个无参数构造方法
3. 要求使用private修饰的成员变量提供对应的操作方法 ==> Setter Getter

10.3 private关键字

private关键字是一个权限修饰符
private修饰的成员变量,成员方法,【构造方法】都是私有化内容,有且只能在类内使用,类外没有任何的操作权限!!!

10.4 Setter和Getter方法

private修饰的成员变量类外是没有任何操作权限,这里需要提供对应的操作方法,setter和getter方法

Setter方法格式:
public void set成员变量名(对应成员变量的数据类型 成员变量的形式参数) {
this.成员变量名 = 成员变量的形式参数;
}

例如:
public void setName(String name) {
	this.name = name;
}

Getter方法格式:
public 对应成员变量的数据类型 get成员变量名() {
return 成员变量;
}

例如:
public String getName() {
	return name;
}

如果成员变量是一个boolean类型,Getter方法有所不同
boolean married;
格式:
public boolean isMarried() {
return married;
}

11. 多类合作

11.1 什么是多类合作

在开发中,除了基本数据类型,大多数情况下,都是类对象操作数据,作为
1. 方法的参数
2. 类定义时成员变量数据类型

11.2 成员变量的数据类型为自定义类型

汽车
发动机
轮胎

class Car
这里需要的数据类型是我们的自定义复合数据类型,自定义类!!!
Engine engine
Tyre tyre

发动机也需要一个类
class Engine
型号
排量

轮胎也需要一个类
class Tyre
型号
尺寸

12. 匿名对象

匿名对象:
new 构造方法(必要的参数);

匿名对象的用途:
1. 使用匿名对象直接调用类内的成员方法
2. 匿名对象直接作为方法的参数

注意:
使用匿名对象不要操作成员变量,有可能是有去无回

优势:
1. 阅后即焚,匿名对象在使用之后 立即被JVM GC收回
2. 解决内存空间,提高效率,简化代码书写

Factory factory = new Factory();        
                                      
// 通过修理店对象,调用修理电脑的方法                  
// 需要的参数是Computer类对象                  
factory.repair(computer);       

/*
Factory类对象
	1. 有且只使用了一次
	2. 该对象中的设置操作是没有什么作用的

问题:
	1. 代码操作感觉不方便
	2. 浪费时间浪费资源,内存资源,JVM效率问题
*/

13. 面向对象的三大特征之继承

13.1 Java中实现继承的方式

继承使用的关键字
extends

格式:
class A extends B{
}
A类是B类的一个子类
B类是A类的唯一父类
Java中的继承是一个单继承模式

基本要求:
1. 子类继承父类之后,可以使用父类的非私有化成员变量和成员方法
【非私有化成员】
2. 子类不能继承得到父类的私有化内容。

13.2 继承的问题

13.2.1 父类的构造方法被调用

在这里插入图片描述

13.2.2 为什么会自动执行父类的无参数构造方法

这里有一个super关键字
1. 调用父类成员方法和成员变量的关键字。
[解决就近原则问题]
2. 用于显式调用父类的构造方法。

super关键字调用父类的构造方法
super(实际参数);
Java编译器会根据实际参数的数据类型,参数顺序,选择对应的父类构造方法执行,初始化父类的成员空间,方法重载机制。

特征:
1. 如果没有显式调用父类的构造方法,默认Java编译器会调用无参父类构造方法使用
2. 根据数据类型选择对应方法
3. super调用构造方法,必须在当前构造方法的第一行

13.2.3 继承带来的问题

子类可以通过继承获取到父类中非私有化方法,但是父类的方法,不一定满足子类的情况。
这里不可能通过重新定义类似的方法名,完成子类特定的符合要求的方法。

13.2.4 方法的重写

解决的问题就是在开发中,父类的方法不适用于子类情况,子类可以重写父类的方法,完成自定义的方法使用
重写之后,在没有增加新的方法名的情况下,重写方法体内容,让方法满足子类,降低了开发压力,提高了效率。

@Override
	严格格式检查
	要求重写方法的和父类中的方法,声明完成一致,返回值类型,方法名和形式参数列表

13.2.5 重写和继承带来的问题

子类继承父类可以直接使用父类的方法,但是在这种情况下我们可以发现父类的方法是一定不能在子类中使用的,但是又没有一个强制要求。

需求:
强制要求子类重写父类的方法,从语法角度约束

13.2.6 abstract关键字

abstract修饰的方法
要求子类强制重写!!!

让Eclipse帮着我们写代码

第一个错误:
Abstract methods do not specify a body
abstract修饰的方法是没有方法体
快速修复提示:
Remove method body
删除方法体

第二个错误:
The abstract method Q in type LOLHero can only be defined by an abstract class
在LOLHero中使用abstract修饰的方法Q,只能定义在abstract修饰的类内 快速修复提示:
Make Type ‘LOLHero’ abstract

第三个错误:
The type Yasuo must implement the inherited abstract method LOLHero.Q()
子类亚索类必须实现继承而来的abstract方法 LOLHero.Q() 快速修复提示:
Add unimplemented methods
添加没有实现的父类中abstract方法

abstract使用总结:
1. abstract修饰的方法没有方法体
2. abstract修饰的方法必须定义在abstract修饰的类内或者interface接口内
3. 一个普通类【非abstract】修饰的类,继承了一个abstract类,那么必须实现在abstract类内的所有abstract,强制要求
4. 如果一个abstract A类继承另一个abstract B类,A类可以选择实现B类中abstract方法。
5. abstract修饰的类内允许普通方法
6. abstract修饰的类不能创建自己的类对象!!!
【原因】
abstract修饰的类内有可能存在abstract修饰的方法,而abstract修饰的方
法是么有方法体的,如果说创建了abstract修饰类对应的对象,不能执行没
有方法体的abstract方法
7. 一个类内没有abstract修饰的方法,那么这个类定义成abstract类有意义吗?
没有必要的!!!无意义的!!!

发布了2 篇原创文章 · 获赞 6 · 访问量 128

猜你喜欢

转载自blog.csdn.net/qq_42581682/article/details/104359501