1.方法
1.1 语法
针对前面的最值、以及查找的问题,我们如果再去处理多个数组,需要做重复的事情。里面的处理的事情是一样,能否将这样的一个功能,提取出来,我们称之为方法
语法:
修饰符 返回值类型 方法名称(形式参数列表) {
方法体
return 值;
}
①修饰符:暂且不关心,拿main去说,public static
②返回值:如果方法没有返回值,则使用void修饰,若有返回值,则使用对应的数据类型【基本+引用】
③方法名称:一般是一种动作,在命名的时候,通常采用动宾结构,命名规范跟变量差不多【小驼峰】
④形式参数列表:数据类型1 参数名1,数据类型2 参数名2,又简称形参
⑤方法体:该方法要执行的功能【代码】
⑥return 值:该部分不是必须的,若你的方法处返回值类型为void,此时就不能加return 值;
注意:1.自定义的方法,属于类的成员,即跟main方法平级
2.方法只能调用,而不能嵌套【在一个方法中,不能定义一个方法】
在定义方法的时候要明确如下2点:
1. 是否有未知量参与,方法才能执行:若有未知量,此时需要定义形参
2. 方法是否需要返回值--->如果你方法执行完之后,它的结果你想给别人【给别的变量赋值,或者在表达式、输出语句中】使用,此时需要带返回值
1.2 方法之HelloWorld
需求1:求2个或n个整数的和
分析:
①哪两个数知道不?只有在调用这个方法的时候,传入值时才知道是什么数字,这个传入的值,我们称之为实际参数,简称实参
②是否需要返回值:看你的sum是否需要给别人使用【表达式、输出语句等】
/**
* 1.方法的定义
* 2.方法重载:
* 前提:在同一个类中
* 条件:方法名相同,参数列表不同【个数、数据类型、顺序】,跟返回值的类型、修饰符无关
* 3.可变参数:jdk1.5的特性
* 注意点:可变参数一定放在形参的最后 数据类型...形参名称
* @author azzhu
* @create 2020-06-02 10:31:15
*/
public class Test04_Method {
public static void main(String[] args) {
System.out.println(sum(10, 20));
System.out.println(sum(30, 40));
sum(10,20,30);
sum(10);
System.out.println(sum(10, 20, 30, 444, 22, 22));
}
/**
* 求和
* @param num1 操作数1
* @param num2 操作数2
* @return 返回两数的结果
*/
public static double sum(double num1,double num2) {
return num1 + num2;
}
public static void sum(double num1,int num2,int num3) {
System.out.println(num1+num2+num3);
}
public static double sum(double ... num) {
double sum = 0;
for (double v : num) {
sum += v;
}
return sum;
}
}
1.3 方法之数组最值&范围查找
需求:将前面的求最值、范围查找,实现代码的复用【重复使用】,把这个功能,写成一个方法
/**
* 在某个数组中,查找指定的元素是否存在
* @param starIndex
* @param endIndex
* @param arrs
* @param val
* @return
*/
public static boolean findValue(int starIndex,int endIndex,int[] arrs,int val) {
boolean flag = false; //默认没有此数,标记
for(int i = starIndex-1;i <= endIndex-1;i++) {
if(arrs[i] == val) {
flag = true;
break;
}
}
return flag;
}
1.4 方法之输出数组元素
需求:直接sout(数组名)
,输出的是一个类似这种[I@1540e19d
地址值,我们期望的是输出每一个元素,且加入我们期望的格式,比如每个元素一行,还是所有元素一行
/**
* 遍历数组元素
* @param arr
*/
public static void printArray(int[] arr) {
if(arr != null) {
for (int i : arr) {
System.out.println(i);
}
}
}
1.5 方法之删除一个数组元素
需求:输入一个值,判断该值在数组中是否存在,若存在,则删除;若不存在,则提示:”你要删除的x不存在“
把握:数组空间连续,需要移动位置
/**
* 从数组中删除某个元素
* @param val 待删除的元素
* @param arrs 待删除的数组.....
*/
public static void delSomeValueFromArray(int val,int[] arrs) {
//删除之前,可以遍历一下数组元素
printArray(arrs);
//执行删除操作
int index = -1;
for (int i = 0; i < arrs.length; i++) {
if(val == arrs[i]) {
index = i;
break;
}
}
if(index != -1) {
//表明找到了val这个元素
for(int j=index;j<arrs.length-1;j++) {
arrs[j] = arrs[j+1];
}
//最后一位置为默认值
arrs[arrs.length-1] = 0;
} else {
System.out.println("查无此数:"+val);
}
System.out.println("删除之后的效果=======");
printArray(arrs);
}
1.6 方法之数组反转
注意:跟倒序输出的区别
/**
* 数组反转
* @param arr
* @return
*/
public static int[] reverArray(int[] arr) {
if(arr != null) {
for (int i = 0,j=arr.length-1; i <= j; i++,j--) {
//交换元素
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
return arr;
}
1.7 方法之数组插入元素
需求:向String[] names
中插入一个值,插入之后,我们遍历输出
找空位置,我们这里的空位置,就是默认值!
/**
* 向数组中插入一个元素:找第一个null位置
* @param name 待插入的元素
* @param names 待插入的数组
* @return 插入元素后的数组
*/
public static String[] addEleToArray(String name,String[] names) {
int index = -1;
//找空位置
if(names != null && name.length() > 0) {
for (int i = 0; i < names.length; i++) {
if(names[i] == null) {
index = i;
break;
}
}
}
//根据是否找到了空位置,插入元素
if(index != -1) {
names[index] = name;
}
return names;
}
1.8 方法之数组插入算法
插入算法:向一个有序数组中,插入一个值val,保证原来的数组依然有序。
思想:以降序为例,找第一个比要插入数小的元素,即为要插入数的index,index及其后面的元素,要向后移动,移动完之后,将要插入的元素方法到index处,arr[index]=val
/**
* 插入算法
* @param val
* @param arr
* @return
*/
public static int[] insertToArray(int val,int[] arr) {
//找位置
int index = -1;
if(arr != null && arr.length > 0) {
for (int i = 0; i < arr.length; i++) {
if(arr[i] > val) {
index = i;
break;
}
}
if(index != -1) {
System.out.println("======>"+index);
//表明找打了位置
//移动元素的过程
for (int i = arr.length-2; i >= index; i--) {
arr[i+1] = arr[i];
}
arr[index] = val;
} else {
arr[arr.length-1] =val;
}
}
return arr;
}
1.9 线性查找+二分查找
二分查找:要求数组必须是有序的
重点掌握思想
/**
* 实现二分查找,重点是掌握思想,每次都会一分两半,重点是改变head和tail
* @param val
* @param arrs
* @return
*/
public static int binarySearch(int val,int[] arrs) {
int index = -1;
if(arrs != null && arrs.length>0) {
int head = 0;
int tail = arrs.length-1;
while (head <= tail) {
int mid = (head+tail)>>1;
if(val == arrs[mid]) {
//要找到值,正好是中间值
index = mid;
break;
} else if(val < arrs[mid]) {
head = mid+1;
} else {
tail = mid-1;
}
}
}
return index;
}
注意:代码跟Arrays.binarySearc()类似
2.多重循环
以双重为例,6种组合
玩双重循环,其实就玩规律
需求:打印m*n的*
,*是一个一个输出的
练习:打印一个等腰三角形
3.Arrays工具类
在jdk中提供了Arrays类,专门用于数组操作
//Arrays工具类的使用
int[] scores = {12,56,87,16,24};
//System.out.println(scores);
//1.Arrays.toString():输出数组元素
System.out.println(Arrays.toString(scores));
//2.Arrays.sort():默认升序,字母字典序
Arrays.sort(scores);
System.out.println(Arrays.toString(scores));
//3.Arrays.binarySearch
System.out.println(Arrays.binarySearch(scores, 87));
//4.Arrays.fill() 填充某个数组
int[] ages = new int[3];
Arrays.fill(ages,4);
System.out.println(Arrays.toString(ages));
//5.Arrays.copyOf
int[] newScores = Arrays.copyOf(scores, 2);
System.out.println(Arrays.toString(newScores));
//6.Arrays.equals
System.out.println(Arrays.equals(scores, newScores));
注意,copyOf的源码
public static int[] copyOf(int[] original, int newLength) {
int[] copy = new int[newLength];
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
4.方法重载[面试]
需求:写一个求和的方法,但是参数的个数不限定
为了提高方法调用的灵活性,可以在一个类中,定义多个同名方法
前提:在一个类中
条件:
①方法名相同
②形参列表不同(个数、类型、顺序)
③跟修饰符和返回值无关
5.二维数组[了解]
对于二维表的数据,如何存储?可以使用二维数组
本质上没有多维数组,都是一维数组
public class Test09_TwoDimen {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
//需求:输出2个班【每个班3个人】,每个班的平均分、每个班的最高分、最地方
double[][] scores = new double[2][];
// double[] firsrClass = new double[3];
// scores[0] = firsrClass;
// System.out.println(scores);
// double[][] scores = {{},{}};
for (int i = 0; i < scores.length; i++) {
// double sum = 0; //每个班独立计算
System.out.println("输入第"+(i+1)+"个班的成绩:");
System.out.println("输入第"+(i+1)+"个班的人数:");
scores[i] = new double[scanner.nextInt()];
for (int j = 0; j < scores[i].length; j++) {
System.out.println("输入第"+(j+1)+"个人的成绩:");
scores[i][j] = scanner.nextDouble();
}
}
for (int i = 0; i < scores.length; i++) {
double sum = 0; //每个班独立计算
System.out.println("第"+(i+1)+"个班的成绩:");
for (int j = 0; j < scores[i].length; j++) {
// System.out.println("第"+(j+1)+"个人的成绩:"+scores[i][j]);
sum += scores[i][j];
}
System.out.println("第"+(i+1)+"个班的总分:"+sum+",平均分:"+(sum/scores[i].length));
}
}
}
6.排序
针对笔试,常见的有冒泡、选择、快排、希尔
https://github.com/algorithm-visualizer/algorithm-visualizer
6.1 冒泡
时间复杂度为O(N^2)
两两比较,交互位置,比较的轮数是数字的个数-1
需求:
排序前:{4,5,6,3,2,1}
排序后:{1,2,3,4,5,6}
排序原理:
-
比较相邻的元素。如果前一个元素比后一个元素大,就交换这两个元素的位置。
- 对每一对相邻元素做同样的工作,从开始第一对元素到结尾的最后一对元素。最终最后位置的元素就是最大值
public class BubbleSort {
public static void bubbleSort(int[] data) {
System.out.println("开始排序");
int arrayLength = data.length;
//外层循环控制轮数
for (int i = 0; i < arrayLength - 1; i++) {
for (int j = 0; j < arrayLength - 1 - i; j++) {
//涉及到交换位置
if (data[j] > data[j + 1]) {
int temp = data[j + 1];
data[j + 1] = data[j];
data[j] = temp;
}
}
//每一轮比较完之后,输出结果
//System.out.println(Arrays.toString(data));
}
}
public static void main(String[] args) {
//int[] data = { 9, -16, 21, 23, -30, -49, 21, 30, 30 };
int[] data = new int[50000];
for (int i = 0; i < data.length; i++) {
data[i] = (int)(Math.random()*50000);
}
System.out.println("排序之前:\n" + Arrays.toString(data));
//获取起始时间
long startTime = System.currentTimeMillis();
//bubbleSort(data);
Arrays.sort(data);
//获取结束时间
long endTime = System.currentTimeMillis();
System.out.println("耗时:"+(endTime-startTime));
System.out.println("排序之后:\n" + Arrays.toString(data));
}
}
6.2 选择
时间复杂度为O(N^2)
需求:
排序前:{4,6,8,7,9,2,10,1}
排序后:{1,2,4,5,7,8,9,10}
排序原理:
-
每一次遍历的过程中,都假定第一个索引处的元素是最小值,和其他元素处的值依次进行比较,如果当前索引处的值大于其他某个索引处的值,则假定其他某个索引处的值为最小值,最后可以找到最小值所在的索引
-
交换第一个索引处和最小值所在的索引处的值
代码实现:
//排序代码
public class Selection {
/*
对数组a中的元素进行排序
*/
public static void sort(Comparable[] a) {
for(int i=0;i<=a.length-2;i++) {
//假定本次遍历,最小值所在的索引为i
int minIndex = i;
for(int j=i+1;j<a.length;j++) {
//比较最小索引minIndex处的值和索引j处的值
if(greater(a[minIndex],a[j])) {
//更换最小值所在的索引
minIndex = j;
}
}
//交换i索引处和minIndex索引处的值
exch(a,i,minIndex);
}
}
/*
判断v元素是否大于w元素
*/
private static boolean greater(Comparable v,Comparable w) {
return v.vompareTo(w) > 0;
}
/*
数组元素i和j交换位置
*/
private static void exch(Comparable[] a,int i,int j) {
Comparable temp;
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
//测试代码
public class Test {
public static void main(String[] args) {
Integer[] a = {4,6,8,7,9,2,10,1};
Selection.sort(a);
System.out.println(Arrays.toString(a));
}
}
6.3 插入
插入排序(Insertion sort)是一种简单直观且稳定的排序算法。
插入排序的工作方式非常像人们排序一手扑克牌一样。开始时,我们的左手为空并且桌子上的牌面朝下,然后,我们每次从桌子上拿走一张牌并将它插入左手中正确的位置。为了找到一张牌的正确位置,我们从右到左将它与已经在手中的每张牌进行比较,如下图所示:
需求:
排序前:{4,3,2,10,12,1,5,6}
排序后:{1,2,3,4,5,6,10,12}
排序原理:
- 把所有的元素分为两组,已经排序的和未排序的;
- 找到未排序的组中的第一个元素,向已经排序的组中进行插入;
- 倒序遍历已经排序的元素,依次和待插入的元素进行比较,直到找到一个元素小于等于待插入元素,那么就把待插入元素放到这个位置,其他的元素向后移动一位
插入排序的代码实现:
//排序代码
public class Insertion {
/*
对数组a中的元素进行排序
*/
public static void sort(Comparable[] a) {
for(int i=1;i<a.length;i++) {
//当前元素为a[i],依次和i前面的元素比较,找到一个小于等于a[i]的元素
for(int j=i;j>=0;j--) {
if(greater(a[j-1],a[j])) {
//交互元素
exch(a,j-1,j);
} else {
//找到了该元素,结束
break;
}
}
}
}
/*
判断v元素是否大于w元素
*/
private static boolean greater(Comparable v,Comparable w) {
return v.vompareTo(w) > 0;
}
/*
数组元素i和j交换位置
*/
private static void exch(Comparable[] a,int i,int j) {
Comparable temp;
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
//测试代码
public class Test {
public static void main(String[] args) {
Integer[] a = {4,3,2,10,12,1,5,6};
Insertion.sort(a);
System.out.println(Arrays.toString(a));
}
}
6.4 快排
原理:
public class QuickSort {
private static void swap(int[] data, int i, int j) {
int temp = data[i];
data[i] = data[j];
data[j] = temp;
}
private static void subSort(int[] data, int start, int end) {
if (start < end) {
int base = data[start];
int low = start;
int high = end + 1;
while (true) {
while (low < end && data[++low] - base <= 0)
;
while (high > start && data[--high] - base >= 0)
;
if (low < high) {
swap(data, low, high);
} else {
break;
}
}
swap(data, start, high);
subSort(data, start, high - 1);//递归调用
subSort(data, high + 1, end);
}
}
public static void quickSort(int[] data){
subSort(data,0,data.length-1);
}
public static void main(String[] args) {
int[] data = { 9, -16, 30, 23, -30, -49, 25, 21, 30 };
System.out.println("排序之前:\n" + Arrays.toString(data));
quickSort(data);
System.out.println("排序之后:\n" + Arrays.toString(data));
}
}
6.5 堆排序
涉及到数据结构
6.6 比较
7.面向对象
7.1 面向对象vs 面向过程
需求:买电脑
面向过程:从挑选到最终下单,这一系列过程,都是你自己完成的。亲力亲为,动作的执行者。
面向对象:找一个懂行的熟人张三,你只要告知价位即可。动作的指挥着。
面向对象就是:找合适的对象帮你干活
7.2 面向对象编程OOP vs 面向过程编程
OOP:(OrientedObject Programming),核心是找一个对象,主要是分析对象的特征【静态特征和动态特征】。
7.3 对象和类的关系
先去发现身边的对象,进而分析它的特征【属性和方法】。
对象是客观存在的实体/事物,不一定是非要看得见摸得着的。万物皆对象
张三:存在的
属性【静态特征】:身高、年龄、名字、… ------》名词
注意:168cm,属性值
方法【动态特征】:吃饭、睡觉、学习、… -----》动宾结构
李四:存在的
属性【静态特征】:身高、年龄、名字、… ------》名词
方法【动态特征】:吃饭、睡觉、学习、… -----》动宾结构
类:类是一个抽象的概念,可以理解为一个模版。那么在java的世界中,我们的对象都是通过类创建出来的。
即只有对象才能帮你干活。
思考:java本身已经提供了很多类?Java能否穷举一切类?可以将自定义类的功能开放给开发者,让我们根据实际业务去定义类。
在设计类的时候,找属性和方法的时候,要根据具体的场景;而不是且也不能穷举出所有。
7.4 对象的创建和使用
需求:创建一个学生类,并创建两个学生对象,为属性赋值,同时调用方法
- 创建一个类
语法 :
修饰符 class 类名 {
//属性
//方法
}
注意:类名的命名规范
1.类名首字母大写
2.若由多个单词构成,则每个单词首字母大写
3.组成:跟变量差不多
public class Student {
//分析student有哪些属性和方法
String name; //对比之前,变量的定义范围 成员变量 局部变量
int stuNo;
public void showInfo() {
System.out.println("我叫:"+name+",学号:"+stuNo);
}
}
- 创建和使用对象
public class TestStudent {
public static void main(String[] args) {
//1.如何通过类去创建一个对象
//类名 对象名 = new 类名();
Student zs = new Student();
Student ls = new Student();
//2.为对象的属性赋值
zs.name = "张三";
zs.stuNo = 1001;
//3.获取对象的属性值
System.out.println(zs.name);
//4.调用方法,通过对象名.方法名(实参)
zs.showInfo();
ls.showInfo();
}
}
练习:写两个类Student、Teacher;分别创建两个对象,调用方法showInfo
7.5 构造方法
构造方法【构造器】是一种特殊的方法,特殊在哪?
注意:一旦我们显示定义有参构造方法,则默认的无参将失效。若就想使用无参,自己写一个!
一旦我们定义有参,你就把无参自己写上!
- 方法名称跟类名一致
- 没有返回值,连void也不能有
- 构造方法也有重载
- jdk默认提供一个无参构造
作用:
- 创建对象
- 为对象初始化属性值
7.6 this的使用
代表:当前对象
用法:
- 调用属性:主要解决形参跟属性名称一致的问题
- 调用方法
- 在构造方法中调用其他的构造方法,但是只能位于第一行
8.练习
-
买双色球,规则(1-33红中选6不重复数字;1-16篮中选1)
大体流程:
-
号码是在范围之内:红[1,33],篮[1,16] —》预先存在数组中
-
投注,买家选择号码6红[放入到数组中]+1篮 int ----》随机
1-33红中,如何随机取6个且不重复。计数器,随机出来一个,将这个值置为0【表示已经取过了】
-
摇奖过程:6+1 红球数组+1篮球int --》手动输入
-
遍历红球数组,统计中奖的红球个数;篮球要么1个,要么0个
-
根据红蓝个数,去看中几等奖
-
-
数组的常见使用【增删改查,必须要会】
-
【扩展】使用学过的知识,实现一个可变数组【当数组元素达到原来长度的75%时,进行扩容,扩容为原来的1.5倍 old+old >>1】 ----》不用交
-
空心菱形
-
通过媒婆搭线,实现男女婚介匹配
具体需求如下:
Boy:name、wealth、getAGirl(Girl girl)
Girl:name、faceValue、marryTo(Boy boy)
MeiPo:定义一个方法,双方先自我介绍一下【未截图】,若男wealth>1000且faceValue>100,则双
方都愿意,匹配成功
否则,肯定有一方条件不满足,或者双方都不满足