JAVA中 Lambda 方法引用 算法

news2025/1/12 9:38:44

算法和数据结构

一、Arrays类

接下来学习的类叫做Arrays,其实Arrays并不是重点,但是我们通过Arrays这个类的学习有助于我们理解下一个知识点Lambda的学习。所以我们这里先学习Arrays,再通过Arrays来学习Lamdba这样学习会更丝滑一些_.

1.1 Arrays基本使用

先认识一下Arrays是干什么用的,Arrays是操作数组的工具类,它可以很方便的对数组中的元素进行遍历、拷贝、排序等操作。

下面我们用代码来演示一下:遍历、拷贝、排序等操作。需要用到的方法如下
在这里插入图片描述

/**
 * 目标:掌握Arrays类的常用方法。
 */
public class ArraysTest1 {
    public static void main(String[] args) {
        // 1、public static String toString(类型[] arr): 返回数组的内容
        int[] arr = {10, 20, 30, 40, 50, 60};
        System.out.println(Arrays.toString(arr));

        // 2、public static 类型[] copyOfRange(类型[] arr, 起始索引, 结束索引) :拷贝数组(指定范围,包前不包后)
        int[] arr2 = Arrays.copyOfRange(arr, 1, 4);
        System.out.println(Arrays.toString(arr2));

        // 3、public static copyOf(类型[] arr, int newLength):拷贝数组,可以指定新数组的长度。
        int[] arr3 = Arrays.copyOf(arr, 10);
        System.out.println(Arrays.toString(arr3));

        // 4、public static setAll(double[] array, IntToDoubleFunction generator):把数组中的原数据改为新数据又存进去。
        double[] prices = {99.8, 128, 100};
        //                  0     1    2
        // 把所有的价格都打八折,然后又存进去。
        Arrays.setAll(prices, new IntToDoubleFunction() {
            @Override
            public double applyAsDouble(int value) {
                // value = 0  1  2
                return prices[value] * 0.8;
            }
        });
        System.out.println(Arrays.toString(prices));

        // 5、public static void sort(类型[] arr):对数组进行排序(默认是升序排序)
        Arrays.sort(prices);
        System.out.println(Arrays.toString(prices));
    }
}

1.2 Arrays操作对象数组

刚才我们使用Arrays操作数组时,数组中存储存储的元素是int类型、double类型,是可以直接排序的,而且默认是升序排列。

如果数组中存储的元素类型是自定义的对象,如何排序呢?接下来,我们就学习一下Arrays如何对对象数组进行排序。

首先我们要准备一个Student类,代码如下:

public class Student implements Comparable<Student>{
    private String name;
    private double height;
    private int age;
	
    public Student(String name, double height, int age) {
        this.name = name;
        this.height = height;
        this.age = age;
    }

	@Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", height=" + height +
                ", age=" + age +
                '}';
    }
}

然后再写一个测试类,往数组中存储4个学生对象,代码如下。此时,运行代码你会发现是会报错的。

public class ArraysTest2 {
    public static void main(String[] args) {
        // 目标:掌握如何对数组中的对象进行排序。
        Student[] students = new Student[4];
        students[0] = new Student("蜘蛛精", 169.5, 23);
        students[1] = new Student("紫霞", 163.8, 26);
        students[2] = new Student("紫霞", 163.8, 26);
        students[3] = new Student("至尊宝", 167.5, 24);

        // 1、public static void sort(类型[] arr):对数组进行排序。
		Arrays.sort(students);
		System.out.println(Arrays.toString(students));
    }
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

上面的代码为什么会报错呢?因为Arrays根本就不知道按照什么规则进行排序。为了让Arrays知道按照什么规则排序,我们有如下的两种办法。

  • **排序方式1:**让Student类实现Comparable接口,同时重写compareTo方法。Arrays的sort方法底层会根据compareTo方法的返回值是正数、负数、还是0来确定谁大、谁小、谁相等。代码如下:
public class Student implements Comparable<Student>{
    private String name;
    private double height;
    private int age;
    
    //...get、set、空参数构造方法、有参数构造方法...自己补全

    // 指定比较规则
    // this  o
    @Override
    public int compareTo(Student o) {
        // 约定1:认为左边对象 大于 右边对象 请您返回正整数
        // 约定2:认为左边对象 小于 右边对象 请您返回负整数
        // 约定3:认为左边对象 等于 右边对象 请您一定返回0
		/* if(this.age > o.age){
            return 1;
        }else if(this.age < o.age){
            return -1;
        }
        return 0;*/

        //上面的if语句,也可以简化为下面的一行代码
        return this.age - o.age; // 按照年龄升序排列
        // return o.age - this.age; // 按照年龄降序排列
    }
    
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", height=" + height +
                ", age=" + age +
                '}';
    }
}
  • **排序方式2:**在调用Arrays.sort(数组,Comparator比较器);时,除了传递数组之外,传递一个Comparator比较器对象。Arrays的sort方法底层会根据Comparator比较器对象的compare方法方法的返回值是正数、负数、还是0来确定谁大、谁小、谁相等。代码如下
public class ArraysTest2 {
    public static void main(String[] args) {
        // 目标:掌握如何对数组中的对象进行排序。
        Student[] students = new Student[4];
        students[0] = new Student("蜘蛛精", 169.5, 23);
        students[1] = new Student("紫霞", 163.8, 26);
        students[2] = new Student("紫霞", 163.8, 26);
        students[3] = new Student("至尊宝", 167.5, 24);

		// 2、public static <T> void sort(T[] arr, Comparator<? super T> c)
        // 参数一:需要排序的数组
        // 参数二:Comparator比较器对象(用来制定对象的比较规则)
        Arrays.sort(students, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                // 制定比较规则了:左边对象 o1   右边对象 o2
                // 约定1:认为左边对象 大于 右边对象 请您返回正整数
                // 约定2:认为左边对象 小于 右边对象 请您返回负整数
                // 约定3:认为左边对象 等于 右边对象 请您一定返回0
//                if(o1.getHeight() > o2.getHeight()){
//                    return 1;
//                }else if(o1.getHeight() < o2.getHeight()){
//                    return -1;
//                }
//                return 0; // 升序
                 return Double.compare(o1.getHeight(), o2.getHeight()); // 升序
                // return Double.compare(o2.getHeight(), o1.getHeight()); // 降序
            }
        });
        System.out.println(Arrays.toString(students));
    }
}

二、Lambda表达式

接下来,我们学习一个JDK8新增的一种语法形式,叫做Lambda表达式。作用:用于简化匿名内部类代码的书写。

2.1 Lambda表达式基本使用

怎么去简化呢?Lamdba是有特有的格式的,按照下面的格式来编写Lamdba。

(被重写方法的形参列表) -> {
    被重写方法的方法体代码;
}

需要给说明一下的是,在使用Lambda表达式之前,必须先有一个接口,而且接口中只能有一个抽象方法。(注意:不能是抽象类,只能是接口)

像这样的接口,我们称之为函数式接口,只有基于函数式接口的匿名内部类才能被Lambda表达式简化。

public interface Swimming{
    void swim();
}

有了以上的Swimming接口之后,接下来才能再演示,使用Lambda表达式,简化匿名内部类书写。

public class LambdaTest1 {
    public static void main(String[] args) {
        // 目标:认识Lambda表达式.
        //1.创建一个Swimming接口的匿名内部类对象
		Swimming s = new Swimming(){
             @Override
             public void swim() {
                 System.out.println("学生快乐的游泳~~~~");
             }
         };
         s.swim();
		
        //2.使用Lambda表达式对Swimming接口的匿名内部类进行简化
        Swimming s1 = () -> {
              System.out.println("学生快乐的游泳~~~~");
        };
        s1.swim();
    }
}

好的,我们现在已经知道Lamdba表达式可以简化基于函数式接口的匿名内部类的书写。接下来,我们可以把刚才使用Arrays方法时的代码,使用Lambda表达式简化一下了。

public class LambdaTest2 {
    public static void main(String[] args) {
        // 目标:使用Lambda简化函数式接口。
        double[] prices = {99.8, 128, 100};
		//1.把所有元素*0.8: 先用匿名内部类写法
        Arrays.setAll(prices, new IntToDoubleFunction() {
            @Override
            public double applyAsDouble(int value) {
                // value = 0  1  2
                return prices[value] * 0.8;
            }
        });
		//2.把所有元素*0.8: 改用Lamdba表达式写法
        Arrays.setAll(prices, (int value) -> {
                return prices[value] * 0.8;
        });

        System.out.println(Arrays.toString(prices));
        System.out.println("-----------------------------------------------");
		
        Student[] students = new Student[4];
        students[0] = new Student("蜘蛛精", 169.5, 23);
        students[1] = new Student("紫霞", 163.8, 26);
        students[2] = new Student("紫霞", 163.8, 26);
        students[3] = new Student("至尊宝", 167.5, 24);
		//3.对数组中的元素按照年龄升序排列: 先用匿名内部类写法
        Arrays.sort(students, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return Double.compare(o1.getHeight(), o2.getHeight()); // 升序
            }
        });
		//4.对数组中的元素按照年龄升序排列: 改用Lambda写法
        Arrays.sort(students, (Student o1, Student o2) -> {
                return Double.compare(o1.getHeight(), o2.getHeight()); // 升序
        });
        System.out.println(Arrays.toString(students));
    }
}

好的,各位同学,恭喜大家!到这里,你已经学会了Lambda表达式的基本使用了。

2.2 Lambda表达式省略规则

刚才我们学习了Lambda表达式的基本使用。Java觉得代码还不够简单,于是还提供了Lamdba表达式的几种简化写法。具体的简化规则如下

1.Lambda的标准格式
	(参数类型1 参数名1, 参数类型2 参数名2)->{
		...方法体的代码...
		return 返回值;
	}

2.在标准格式的基础上()中的参数类型可以直接省略
	(参数名1, 参数名2)->{
		...方法体的代码...
		return 返回值;
	}
	
3.如果{}总的语句只有一条语句,则{}可以省略、return关键字、以及最后的“;”都可以省略
	(参数名1, 参数名2)-> 结果
	
4.如果()里面只有一个参数,则()可以省略
	(参数名)->结果

接下来从匿名内部类开始、到Lambda标准格式、再到Lambda简化格式,一步一步来简化一下。同学们体会一下简化的过程。

public class LambdaTest2 {
    public static void main(String[] args) {
        // 目标:使用Lambda简化函数式接口。
        double[] prices = {99.8, 128, 100};
		//1.对数组中的每一个元素*0.8: 匿名内部类写法
        Arrays.setAll(prices, new IntToDoubleFunction() {
            @Override
            public double applyAsDouble(int value) {
                // value = 0  1  2
                return prices[value] * 0.8;
            }
        });
		//2.需求:对数组中的每一个元素*0.8,使用Lambda表达式标准写法
        Arrays.setAll(prices, (int value) -> {
                return prices[value] * 0.8;
        });
		//3.使用Lambda表达式简化格式1——省略参数类型
        Arrays.setAll(prices, (value) -> {
            return prices[value] * 0.8;
        });
		//4.使用Lambda表达式简化格式2——省略()
        Arrays.setAll(prices, value -> {
            return prices[value] * 0.8;
        });
        //5.使用Lambda表达式简化格式3——省略{}
        Arrays.setAll(prices, value -> prices[value] * 0.8 );

        System.out.println(Arrays.toString(prices));
        
        System.out.println("------------------------------------

        Student[] students = new Student[4];
        students[0] = new Student("蜘蛛精", 169.5, 23);
        students[1] = new Student("紫霞", 163.8, 26);
        students[2] = new Student("紫霞", 163.8, 26);
        students[3] = new Student("至尊宝", 167.5, 24);
		
        //1.使用匿名内部类
        Arrays.sort(students, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return Double.compare(o1.getHeight(), o2.getHeight()); // 升序
            }
        });
		//2.使用Lambda表达式表达式——标准格式
        Arrays.sort(students, (Student o1, Student o2) -> {
                return Double.compare(o1.getHeight(), o2.getHeight()); // 升序
        });
		//3.使用Lambda表达式表达式——省略参数类型
        Arrays.sort(students, ( o1,  o2) -> {
            return Double.compare(o1.getHeight(), o2.getHeight()); // 升序
        });
		//4.使用Lambda表达式表达式——省略{}
        Arrays.sort(students, ( o1,  o2) -> Double.compare(o1.getHeight(), o2.getHeight()));


        System.out.println(Arrays.toString(students));
    }
}

到这里,恭喜你,对Lamdba表达式的所有写法,就学习完毕了。

三、JDK8新特性(方法引用)

各位小伙伴,接下来我们学习JDK8的另一个新特性,叫做方法引用。我们知道Lambda是用来简化匿名代码的书写格式的,而方法引用是用来进一步简化Lambda表达式的,它简化的更加过分。

到这里有小伙伴可能就想慰问Java爸爸了:“之前的代码挺好的呀!好不容易学会,你又来搞这些,把我都搞晕了。“ 说句大实话,确实有这样的问题,学习新的东西肯定会增加我们的学习成本,从心理上来说多少是有写抗拒的。但是从另一个角度想,一旦我们学会了,会大大简化我们的代码书写,提高我们编写代码的效率,而且这些新的语法都是有前提条件的,遇到的时候就简化得了。再退一步想,就算你没有学会,还是用以前的办法一点问题也没有。

给大家交代清楚了,学习方法引用可能存在的一些心理特点之后,接下来我们再正式学习方法引用的代码怎么编写。

3.1 静态方法引用

我们先学习静态方法的引用,还是用之前Arrays代码来做演示。现在准备好下面的代码

public class Test1 {
    public static void main(String[] args) {
        Student[] students = new Student[4];
        students[0] = new Student("蜘蛛精", 169.5, 23);
        students[1] = new Student("紫霞", 163.8, 26);
        students[2] = new Student("紫霞", 163.8, 26);
        students[3] = new Student("至尊宝", 167.5, 24);

        // 原始写法:对数组中的学生对象,按照年龄升序排序
        Arrays.sort(students, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getAge() - o2.getAge(); // 按照年龄升序排序
            }
        });

        // 使用Lambda简化后的形式
        Arrays.sort(students, (o1, o2) -> o1.getAge() - o2.getAge());
    }
}

现在,我想要把下图中Lambda表达式的方法体,用一个静态方法代替
在这里插入图片描述
准备另外一个类CompareByData类,用于封装Lambda表达式的方法体代码;

public class CompareByData {
    public static int compareByAge(Student o1, Student o2){
        return o1.getAge() - o2.getAge(); // 升序排序的规则
    }
}

现在我们就可以把Lambda表达式的方法体代码,改为下面的样子

Arrays.sort(students, (o1, o2) -> CompareByData.compareByAge(o1, o2));

Java为了简化上面Lambda表达式的写法,利用方法引用可以改进为下面的样子。**实际上就是用类名调用方法,但是把参数给省略了。**这就是静态方法引用

//静态方法引用:类名::方法名
Arrays.sort(students, CompareByData::compareByAge);

3.2 实例方法引用

还是基于上面的案例,我们现在来学习一下实例方法的引用。现在,我想要把下图中Lambda表达式的方法体,用一个实例方法代替
在这里插入图片描述
在CompareByData类中,再添加一个实例方法,用于封装Lambda表达式的方法体
在这里插入图片描述
接下来,我们把Lambda表达式的方法体,改用对象调用方法

CompareByData compare = new CompareByData();
Arrays.sort(students, (o1, o2) -> compare.compareByAgeDesc(o1, o2)); // 降序

最后,再将Lambda表达式的方法体,直接改成方法引用写法。实际上就是用类名调用方法,但是省略的参数。这就是实例方法引用

CompareByData compare = new CompareByData();
Arrays.sort(students, compare::compareByAgeDesc); // 降序

给小伙伴的寄语:一定要按照老师写的步骤,一步一步来做,你一定能学会的!!!

3.3 特定类型的方法引用

各位小伙伴,我们继续学习特定类型的方法引用。在学习之前还是需要给大家说明一下,这种特定类型的方法引用是没有什么道理的,只是语法的一种约定,遇到这种场景,就可以这样用。

Java约定:
    如果某个Lambda表达式里只是调用一个实例方法,并且前面参数列表中的第一个参数作为方法的主调,	后面的所有参数都是作为该实例方法的入参时,则就可以使用特定类型的方法引用。
格式:
	类型::方法名
public class Test2 {
    public static void main(String[] args) {
        String[] names = {"boby", "angela", "Andy" ,"dlei", "caocao", "Babo", "jack", "Cici"};
        
        // 要求忽略首字符大小写进行排序。
        Arrays.sort(names, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                // 制定比较规则。o1 = "Andy"  o2 = "angela"
                return o1.compareToIgnoreCase(o2);
            }
        });
		
        //lambda表达式写法
        Arrays.sort(names, ( o1,  o2) -> o1.compareToIgnoreCase(o2) );
        //特定类型的方法引用!
        Arrays.sort(names, String::compareToIgnoreCase);

        System.out.println(Arrays.toString(names));
    }
}

3.4 构造器引用

各位小伙伴,我们学习最后一种方法引用的形式,叫做构造器引用。还是先说明一下,构造器引用在实际开发中应用的并不多,目前还没有找到构造器的应用场景。所以大家在学习的时候,也只是关注语法就可以了。

现在,我们准备一个JavaBean类,Car类

public class Car {
    private String name;
    private double price;

    public Car() {

    }

    public Car(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

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

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Car{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }
}

因为方法引用是基于Lamdba表达式简化的,所以也要按照Lamdba表达式的使用前提来用,需要一个函数式接口,接口中代码的返回值类型是Car类型

interface CreateCar{
    Car create(String name, double price);
}

最后,再准备一个测试类,在测试类中创建CreateCar接口的实现类对象,先用匿名内部类创建、再用Lambda表达式创建,最后改用方法引用创建。同学们只关注格式就可以,不要去想为什么(语法就是这么设计的)。

public class Test3 {
    public static void main(String[] args) {
        // 1、创建这个接口的匿名内部类对象。
        CreateCar cc1 = new CreateCar(){
            @Override
            public Car create(String name, double price) {
                return new Car(name, price);
            }
        };
		//2、使用匿名内部类改进
        CreateCar cc2 = (name,  price) -> new Car(name, price);

        //3、使用方法引用改进:构造器引用
        CreateCar cc3 = Car::new;
        
        //注意:以上是创建CreateCar接口实现类对象的几种形式而已,语法一步一步简化。
        
        //4、对象调用方法
        Car car = cc3.create("奔驰", 49.9);
        System.out.println(car);
    }
}

四、常见算法

1.1 认识算法

接下来,我们认识一下什么是算法。算法其实是解决某个实际问题的过程和方法。比如百度地图给你规划路径,计算最优路径的过程就需要用到算法。再比如你在抖音上刷视频时,它会根据你的喜好给你推荐你喜欢看的视频,这里也需要用到算法。

我们为什么要学习算法呢?主要目的是训练我们的编程思维,还有就是面试的时候,面试官也喜欢问一下算法的问题来考察你的技术水平。最后一点,学习算法是成为一个高级程序员的必经之路。

当然我们现在并不会学习非常复杂的算法,万丈高楼平地起,我们现在只需要学习几种常见的基础算法就可以了。而且Java语言本身就内置了一些基础算法给我们使用,实际上自己也不会去写这些算法。

在这里插入图片描述

1.2 冒泡排序

接下来,我们学习一种算法叫排序算法,它可以价格无序的整数,排列成从小到大的形式(升序),或者从大到小的形式(降序)

排序算法有很多种,我们这里只学习比较简单的两种,一种是冒泡排序,一种是选择排序。学习算法我们先要搞清楚算法的流程,然后再去“推敲“如何写代码。(注意,我这里用的次是推敲,也就是说算法这样的代码并不是一次成型的,是需要反复修改才能写好的)。
在这里插入图片描述
先来学习冒泡排序,先来介绍一下,冒泡排序的流程

冒泡排序核心思路:每次将相邻的两个元素继续比较
如下图所示:
   第一轮比较 3次
   第二轮比较 2次
   第三轮比较 1

在这里插入图片描述

public class Test1 {
    public static void main(String[] args) {
        // 1、准备一个数组
        int[] arr = {5, 2, 3, 1};

        // 2、定义一个循环控制排几轮
        for (int i = 0; i < arr.length - 1; i++) {
            // i = 0  1  2           【5, 2, 3, 1】    次数
            // i = 0 第一轮            0   1   2         3
            // i = 1 第二轮            0   1             2
            // i = 2 第三轮            0                 1

            // 3、定义一个循环控制每轮比较几次。
            for (int j = 0; j < arr.length - i - 1; j++) {
                // 判断当前位置的元素值,是否大于后一个位置处的元素值,如果大则交换。
                if(arr[j] > arr[j+1]){
                    int temp = arr[j + 1];
                    arr[j + 1] = arr[j];
                    arr[j] = temp;
                }
            }
        }
        System.out.println(Arrays.toString(arr));
    }
}

1.2 选择排序

刚才我们学习了冒泡排序,接下来我们学习了另一种排序方法,叫做选择排序。按照我们刚才给大家介绍的算法的学习方式。先要搞清楚算法的流程,再去推敲代码怎么写。

所以我们先分析选择排序算法的流程:选择排序的核心思路是,每一轮选定一个固定的元素,和其他的每一个元素进行比较;经过几轮比较之后,每一个元素都能比较到了。
在这里插入图片描述
接下来,按照选择排序的流程编写代码

ublic class Test2 {
    public static void main(String[] args) {
        // 1、准备好一个数组
        int[] arr = {5, 1, 3, 2};
        //           0  1  2  3

        // 2、控制选择几轮
        for (int i = 0; i < arr.length - 1; i++) {
            // i = 0 第一轮    j = 1 2 3
            // i = 1 第二轮    j = 2 3
            // i = 2 第三轮    j = 3
            // 3、控制每轮选择几次。
            for (int j = i + 1; j < arr.length; j++) {
                // 判断当前位置是否大于后面位置处的元素值,若大于则交换。
                if(arr[i] > arr[j]){
                    int temp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = temp;
                }
            }
        }
        System.out.println(Arrays.toString(arr));
    }
}

1.3 查找算法

接下来,我们学习一个查找算法叫做二分查找。在学习二分查找之前,我们先来说一下基本查找,从基本查找的弊端,我们再引入二分查找,这样我们的学习也会更加丝滑一下。

**先聊一聊基本查找:**假设我们要查找的元素是81,如果是基本查找的话,只能从0索引开始一个一个往后找,但是如果元素比较多,你要查找的元素比较靠后的话,这样查找的此处就比较多。性能比较差。
在这里插入图片描述
再讲二分查找:二分查找的主要特点是,每次查找能排除一般元素,这样效率明显提高。但是二分查找要求比较苛刻,它要求元素必须是有序的,否则不能进行二分查找。

  • 二分查找的核心思路
1步:先定义两个变量,分别记录开始索引(left)和结束索引(right)2步:计算中间位置的索引,mid = (left+right)/2;3步:每次查找中间mid位置的元素,和目标元素key进行比较
		如果中间位置元素比目标元素小,那就说明mid前面的元素都比目标元素小
			此时:left = mid+1
    	如果中间位置元素比目标元素大,那说明mid后面的元素都比目标元素大
    		此时:right = mid-1
		如果中间位置元素和目标元素相等,那说明mid就是我们要找的位置
			此时:把mid返回		
注意:一搬查找一次肯定是不够的,所以需要把第1步和第2步循环来做,只到left>end就结束,如果最后还没有找到目标元素,就返回-1. 

在这里插入图片描述

/**
 * 目标:掌握二分查找算法。
 */
public class Test3 {
    public static void main(String[] args) {
        // 1、准备好一个数组。
        int[] arr = {7, 23, 79, 81, 103, 127, 131, 147};

        System.out.println(binarySearch(arr, 150));

        System.out.println(Arrays.binarySearch(arr, 81));
    }

    public static int binarySearch(int[] arr, int data){
        // 1、定义两个变量,一个站在左边位置,一个站在右边位置
        int left = 0;
        int right = arr.length - 1;

        // 2、定义一个循环控制折半。
        while (left <= right){
            // 3、每次折半,都算出中间位置处的索引
            int middle = (left + right) / 2;
            // 4、判断当前要找的元素值,与中间位置处的元素值的大小情况。
            if(data < arr[middle]){
                // 往左边找,截止位置(右边位置) = 中间位置 - 1
                right = middle - 1;
            }else if(data > arr[middle]){
                // 往右边找,起始位置(左边位置) = 中间位置 + 1
                left = middle + 1;
            }else {
                // 中间位置处的元素值,正好等于我们要找的元素值
                return middle;
            }
        }
        return -1; // -1特殊结果,就代表没有找到数据!数组中不存在该数据!
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1401635.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Qt Quick 项目(第一集Qt Quick UI 项目项目创建)】

# Qt Quick 项目 到底什么是Qt Qml、什么是Qt Quick、QtQuick应用程序与Qt Widget程序有何区别,为了让读者在学习QML之前有一个整体认识,这里先介绍几个Quick项目。 01 Qt Quick UI 项目

Java8的Stream最佳实践

从这一篇文章开始&#xff0c;我们会由浅入深&#xff0c;全面的学习stream API的最佳实践&#xff08;结合我的使用经验&#xff09;&#xff0c;本想一篇写完&#xff0c;但写着写着发现需要写的内容太多了&#xff0c;所以分成一个系列慢慢来说。给大家分享我的经验的同时&a…

【博士每天一篇论文-技术综述】Machine Learning With Echo State Networks 一篇系统讲解ESN知识的五星文章

阅读时间&#xff1a;2023-11-21 1 介绍 年份&#xff1a;2020 作者&#xff1a;徐元超&#xff0c;曼尼托巴大学 期刊&#xff1a; 无 引用量&#xff1a;无 这篇文章是一篇技术报告&#xff0c;从递归神经网络&#xff08;RNNs&#xff09;引入到回声状态网络&#xff08;…

JavaScript基础之JavaScript简介(什么是JavaScript?)

JavaScript简介 JavaScript&#xff0c;通常被缩写为JS&#xff0c;是一种轻量级、跨平台、单线程、解释编译的编程语言。它也被称为网页脚本语言。它以网页开发而闻名&#xff0c;许多非浏览器环境也使用它。 JavaScript是一种弱类型语言。JavaScript可用于客户端开发以及服…

shell编程学习

shell编程学习 变量的高级用法变量替换字符串处理获取字符索引获取子串长度抽取字符串中的子串 案例测试 变量的高级用法 变量替换 ##变量替换&#xff08;贪婪&#xff0c;从前往后匹配&#xff0c;匹配到进行删除&#xff09; test1I love you,you love me echo $test1 han…

Java研学-spring框架(一)

一 概述 1 介绍 Spring框架是一个开源的Java EE应用程序框架&#xff0c;旨在简化Java企业级应用的开发难度和开发周期&#xff0c;主要通过控制反转&#xff08;IoC&#xff09;和面向切面编程&#xff08;AOP&#xff09;等技术实现。   容器&#xff08;Container&#x…

【CVE-2022-22733漏洞复现】

Apache ShardingSphere ElasticJob-UI漏洞 漏洞编号:CVE-2022-22733 文档说明 本文作者:SwBack 创作时间:2024/1/21 19:19:19 知乎:https://www.zhihu.com/people/back-88-87 CSDN:https://blog.csdn.net/qq_30817059 百度搜索: SwBack漏洞描述 Apache ShardingSphere Elast…

Python基础第二篇(Python基础语法)

文章目录 一、字面量二、注释三、变量四、数据类型五、数据类型转换六、标识符七、运算符八、字符串扩展内容&#xff08;1&#xff09;字符串定义&#xff08;2&#xff09;字符串拼接、&#xff08;3&#xff09;字符串格式化&#xff08;4&#xff09;字符串格式化的精度控制…

上位机图像处理和嵌入式模块部署(开篇)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 图像处理是现实生活当中很实用的一门技术。工业上一般采用的是机器视觉&#xff0c;以传统算法和光源控制为主&#xff0c;部分采用了深度学习技术…

MySQL的下载、安装、配置、登录,配置(图+文)(超级详细)

一、 软件的下载 1. 下载地址 官网&#xff1a; https://www.mysql.com 2. 打开官网&#xff0c;点击 DOWNLOADS 然后&#xff0c;点击 MySQL Community(GPL) Downloads 3. 点击 MySQL Community Server 4. 在 General Availability(GA) Releases 中选择适合的版本 …

【C语言基础篇】结构控制(下)转向语句break、continue、goto、return

文章目录 一、break语句 1. break在 while 循环中 2. break在 for 循环中 3. break在 do…while 循环中 4. break在 switch 语句中 5. break 总结 二、continue语句 1. continue在 while 循环中 2. continue在 for 循环中 3. continue在 do...while 循环中 4. con…

Kubernetes网络模型概述

Kubernetes网络模型设计的一个基础原则是&#xff1a;每个Pod都拥有一个独立的IP地址&#xff0c;并假定所有Pod都在一个可以直接连通的、扁平的网络空间中。所以不管这些Pod是否运行在同一个Node中&#xff0c;都要求它们可以直接通过对方的IP进行访问。由于Kubernetes的网络模…

C++泛型编程-类模板的项目实战实现基础的Vector的编写

请设计一个数组模板类&#xff08; Vector &#xff09;&#xff0c;完成对 int 、 char 、 float 、 double 以 及任意的自定义类等类型元素进行管理。 需求 a. 实现构造函数 b. 实现拷贝构造函数 c. 实现 cout << 操作 d. 实现下标访问符 [] 的重载操作 …

中仕教育:应届生可以考军队文职吗?有什么要求?

军队文职&#xff0c;涵盖了各个领域&#xff0c;包括行政、管理、人力资源、后勤等工作岗位&#xff0c;作为国家公务员的一种类型&#xff0c;军队文职同样享有稳定的工作和待遇。 虽然军队文职对所有符合条件的人开放&#xff0c;但对于应届生来说&#xff0c;还需满足以下…

企业Oracle1 数据库管理

Oracle的安装 一、基础表的创建 1.1 切换到scott用户 用sys 账户 登录 解锁scott账户 alter user scott account unlock;conn scott/tiger;发现并不存在scott账户&#xff0c;自己创建一个&#xff1f; 查找资料后发现&#xff0c;scott用户的脚本需要自己执行一下 C:\ap…

Spring:StopWatch

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 一、输出总耗时 二、输出所有任务的耗时和占比 总结 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、输出总耗时 public void stopWatc…

【web 编程技术】基于 B/S 架构的电商平台(java web)

基于 B/S 架构的电商平台&#xff08;java web&#xff09; 课程设计实验目的课程设计实验环境课程设计功能概述课程设计需求分析三层架构图功能列表系统用例图系统活动图-用户端需求分析 课程设计详细设计实现过程数据库BaseServlet 的实现商品显示模块-分页显示所有商品、查看…

【网站项目】基于SSM的274办公自动化管理系统

&#x1f64a;作者简介&#xff1a;多年一线开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

安全防御-基础认知

目录 安全风险能见度不足&#xff1a; 常见的网络安全术语 &#xff1a; 常见安全风险 网络的基本攻击模式&#xff1a; 病毒分类&#xff1a; 病毒的特征&#xff1a; 常见病毒&#xff1a; 信息安全的五要素&#xff1a; 信息安全的五要素案例 网络空间&#xff1a…

flutter项目怎么判断是不是web平台?Unsupported operation: Platform._operatingSystem

如果你使用Platform 这个工具来判断的时候&#xff0c;很有可能会报错&#xff1a; Exception caught by widgets library The following UnsupportedError was thrown building MyApp(dirty): Unsupported operation: Platform._operatingSystem The relevant error-causin…