3.Java基础之方法+双重循环+常见排序+面向对象入门

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}

排序原理:

  1. 比较相邻的元素。如果前一个元素比后一个元素大,就交换这两个元素的位置。

    1. 对每一对相邻元素做同样的工作,从开始第一对元素到结尾的最后一对元素。最终最后位置的元素就是最大值

在这里插入图片描述

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}

排序原理:

  1. 每一次遍历的过程中,都假定第一个索引处的元素是最小值,和其他元素处的值依次进行比较,如果当前索引处的值大于其他某个索引处的值,则假定其他某个索引处的值为最小值,最后可以找到最小值所在的索引

  2. 交换第一个索引处和最小值所在的索引处的值

在这里插入图片描述

代码实现:

//排序代码
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}

排序原理:

  1. 把所有的元素分为两组,已经排序的和未排序的;
  2. 找到未排序的组中的第一个元素,向已经排序的组中进行插入;
  3. 倒序遍历已经排序的元素,依次和待插入的元素进行比较,直到找到一个元素小于等于待插入元素,那么就把待插入元素放到这个位置,其他的元素向后移动一位

在这里插入图片描述

插入排序的代码实现:

//排序代码
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 对象的创建和使用

需求:创建一个学生类,并创建两个学生对象,为属性赋值,同时调用方法

  1. 创建一个类

语法 :

修饰符 class 类名 {
    //属性
    //方法
}
注意:类名的命名规范
1.类名首字母大写
2.若由多个单词构成,则每个单词首字母大写
3.组成:跟变量差不多    
public class Student {
    //分析student有哪些属性和方法
    String name;    //对比之前,变量的定义范围 成员变量 局部变量
    int stuNo;

    public void showInfo() {
        System.out.println("我叫:"+name+",学号:"+stuNo);
    }
}
  1. 创建和使用对象
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 构造方法

构造方法【构造器】是一种特殊的方法,特殊在哪?

注意:一旦我们显示定义有参构造方法,则默认的无参将失效。若就想使用无参,自己写一个!

一旦我们定义有参,你就把无参自己写上!

  1. 方法名称跟类名一致
  2. 没有返回值,连void也不能有
  3. 构造方法也有重载
  4. jdk默认提供一个无参构造

作用:

  1. 创建对象
  2. 为对象初始化属性值

7.6 this的使用

代表:当前对象

用法:

  1. 调用属性:主要解决形参跟属性名称一致的问题
  2. 调用方法
  3. 在构造方法中调用其他的构造方法,但是只能位于第一行

8.练习

  1. 买双色球,规则(1-33红中选6不重复数字;1-16篮中选1)

    大体流程:

    1. 号码是在范围之内:红[1,33],篮[1,16] —》预先存在数组中

    2. 投注,买家选择号码6红[放入到数组中]+1篮 int ----》随机

      1-33红中,如何随机取6个且不重复。计数器,随机出来一个,将这个值置为0【表示已经取过了】

    3. 摇奖过程:6+1 红球数组+1篮球int --》手动输入

    4. 遍历红球数组,统计中奖的红球个数;篮球要么1个,要么0个

    5. 根据红蓝个数,去看中几等奖

在这里插入图片描述

  1. 数组的常见使用【增删改查,必须要会】

  2. 【扩展】使用学过的知识,实现一个可变数组【当数组元素达到原来长度的75%时,进行扩容,扩容为原来的1.5倍 old+old >>1】 ----》不用交

  3. 空心菱形

  4. 通过媒婆搭线,实现男女婚介匹配
    具体需求如下:
    Boy:name、wealth、getAGirl(Girl girl)
    Girl:name、faceValue、marryTo(Boy boy)
    MeiPo:定义一个方法,双方先自我介绍一下【未截图】,若男wealth>1000且faceValue>100,则双
    方都愿意,匹配成功
    否则,肯定有一方条件不满足,或者双方都不满足

在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值