Lambda表达式

第一章 Java为什么引入 Lmabda表达式

目的尽可能轻量级的将代码封装为数据

1.1 什么是Lambda表达式

Lambda表达式也被成为箭头函数、匿名函数、闭包
Lambda表达式体现的是轻量级函数式编程思想
‘->’符号是Lambda表达式的核心符号,符号左侧是操作参数,符号右侧是操作表达式

1.2 Model Code as Data

Model Code As Data,编码及数据,尽可能轻量级的将代码封装为数据
传统解决方案:接口&实现类(匿名内部类)
- 但传统方案存在的问题:
  a 语法冗余(有很多和数据处理无关的代码)
  b this关键字(匿名内部类中,this关键字在内部类型中,变量绑定和变量访问存在很大误区)
  c 变量捕获(内部类型中,当前作用域中的变量的处理,会有一些特殊要求)
  d 数据控制(数据量控制并不是非常友好)等

第二章 函数式接口的概述和定义

2.1函数式接口定义

函数式接口(functuon interface),就是Java类型系统中的接口
函数式接口,是只包含一个接口方法的特殊接口
语义化检测注解:@FunctionalInterface,用来检查函数式接口的合法性

语义化检测注解:@Functionallnterface这是用来检查函数式接口的合法性的注解

==============================================================

函数式接口定义总结:定义一个函数式接口只需要在接口中提供一个接口方法,并在接口上添加@Functionallnterface注解即可,如果添加了多个接口方法,@FunctionAllnterface就会报错,

那么此时也不再是函数式接口,但请注意在一个接口中,默认方法、静态方法、函数式接口是可以共同存在的

默认方法和静态方法使用

这是两个函数式接口例子如下:

定义一个函数式接口只需要在接口中提供一个接口方法,并在接口上添加@FunctionalInterface注解即可,如果添加了多个接口方法,则注解@FunctionalInterface就会报错,那么此时不再是函数式接口,但默认方法,静态接口是允许存在的

默认接口方法的特性

以用户身份认证标记接口为例创建一个实现类 是用来返回用户身份的接口方法

对当前代码进行测试

像以上代码当需求进行变动后,就比如说要求用户返回用户身份后还可以同时获取用户的身份信息,那么就需要修改所有的实现类代码,这是一种不好的行为,因为一个接口方法就应该做到单一职责,那么我们在不修改原本的实习类的方法下,还有哪些办法可以再获取用户的身高信息呢?

  1. 在接口里新增一个接口方法,但是此时该接口不再是函数式接口,就是一个普通接口,再根据着接口书写一个实现类,并重写接口的里面的方法,在实现类的方法里面编写需要 (不满足函数式接口)

  1. 在接口里面使用默认方法(满足函数式接口)

  1. 在接口里面使用静态方法(满足函数式接口)

这样我们就可以直接通过代码来调用默认方法

静态接口方法的特性

以消息发送接口为例,在接口中添加一个静态方法:验证消息格式是否合法

添加一个实现类,重写接口中的方法,节省时间并直接进行了测试

在format方法中,我们只是打印了一句话 消息转换成了------》Hello-World2001/6/12。,并返回了msg,这时候我们可以直接调用接口的静态方法来验证消息的合法性。通过执行结果可以看出,静态方法不会对函数式接口的语义也不会产生影响,总结:默认接口,函数式接口,静态接口可以在一个接口类中同时存在。

从Object中继承的方法不会影响函数式接口

由于java中的类都直接的或者间接的继承了Object类,所以从Object继承的方法,无论是否是抽象的,都不会影响你函数式接口的语义。

例如,在 IUserCredential 中添加一个来自object的方法 toString(),该函数式接口也是不会报错的

总结:默认接口,函数式接口,静态接口,从Object中继承的方法接口是可以在一个接口类中同时存在的。

Lambda表达式和函数式接口的关系

Lambda 只能操作一个方法 Java 中的Lambda表达式就是一个函数式接口的实现

实现接口方法的另一种方式是使用匿名内部类,

通过观察匿名内部类的方式实现接口方法实现类实现接口的方式实现接口方法,就可以发现,其实和数据相关的代码只有

" return “admin”.equals(username) ? “系统管理员” : “普通会员”; " 这一行,其他的代码都是冗余代码,那么能不能对代码进行优化呢?这就要使用到JDK8中的Lambda表达式。

相比较前面的匿名内部类,Lambda表达式实现方式更为简洁

JDK 中常见的函数式接口

jdk8提供的常见函数式接口

java.util.function提供了大量的函数式接口

Predicate:接收参数T对象,返回一个Boolean类型结果

Consumer:接收参数T对象,没有返回值

Function:接收参数T对象,返回R对象

Supplier:不接收任何对象,只通过get()获取指定类型的对象

UnaryOperator:接收参数对象T,执行完业务后,返回更新后的T对象

BinaryOperator: 接收两个参数T对象,执行业务处理后,返回一个T对象

JDK8提供了java.util.function包,提供了常用的函数式功能接口

demo

1.java.util.function.Predicate

接收参数对象T,返回一个boolean类型结果,适合需要判断的场景

2.java.util.function.Consumer

接收参数T,不反回结果

3. java.util.function.Function<T,R>

接收一个参数对象T,返回结果对象R

4. java.util.function.Supplier

不接受参数,提供T对象的创建工厂

5. java.util.function.UnaryOperator

接收参数对象T,返回结果对象T ,常用于适配器模式

6. java.util.function.BinaryOperator

接收两个T对象,返回一个T对象的结果(使用场景:例如对两个对象进行比较,返回较大的结果)

总结:java.util.function提供了大量的函数式接口

Predicate 接收参数对象T,返回一个boolean类型结果

Consumer 接收参数T,不反回结果

Function 接收一个参数对象T,返回结果对象R

Supplier 不接受参数,提供T对象的创建工厂

UnaryOperator 接收参数对象T,返回结果对象T

BinaryOperator 接收两个T对象,返回一个T对象的结果

Lmabda表达式的基本语法

声明:就是 Lambda表达式绑定的接口类型
参数:包含在一对圆括号中,和绑定的接口中的抽象方法中的参数顺序一致。
操作符:->
执行代码块:包含在一对大括号中,出现在操作符的右侧
[接口声明] = (参数) ->{执行代码}               接口名 给接口取名 = (参数)->{执行代码}
package org.example.lambda;

public class LambdaTest {

    @FunctionalInterface
    interface TestLambda1{
        void testLambda();

    }

    public static void main(String[] args) {
      //没有返回值的Lambda表达式
        TestLambda1 testLambda1=()->{
            System.out.println("hello,testLambda1");
        };
        testLambda1.testLambda();// hello,testLambda1

        //如果在执行代码块中,只有一行代码,大括号是可以省略的
        TestLambda1 testLambda2=()-> System.out.println("hello,testLambda2");;
        testLambda2.testLambda();// hello,testLambda2
        

    }
}
package org.example.lambda;

public class LambdaTest {

    @FunctionalInterface
    interface TestLambda1{
        void testLambda();

    }

//    public static void main(String[] args) {
//      //没有返回值的Lambda表达式
//        TestLambda1 testLambda1=()->{
//            System.out.println("hello,testLambda1");
//        };
//        testLambda1.testLambda();// hello,testLambda1
//
//        //如果在执行代码块中,只有一行代码,大括号是可以省略的
//        TestLambda1 testLambda2=()-> System.out.println("hello,testLambda2");;
//        testLambda2.testLambda();// hello,testLambda2
//
//
//    }

    @FunctionalInterface
    interface TestLambda2 {
        void test(String name, int age);
    }

    public static void main(String[] args) {
        //带有参数 但是没有返回值得Lambda表达式和接口
        //带有参数时,要将参数写在小括号中,参数的顺序和接口中定义的顺序相同
        TestLambda2 testLambda1 =(String name, int age)->{
            System.out.println(name+"今年"+age+"岁了");
        };
        testLambda1.test("庞鹏程",21);//庞鹏程今年21岁了

        //在设置参数时,也可以不写参数的类型,JVM会自动推断出参数的类型,以下方式和上面的代码是一样的
        TestLambda2 testLambda2 =(name, age)->{
            System.out.println(name+"今年"+age+"岁了");
        };
        testLambda1.test("庞鹏程",21);//庞鹏程今年21岁了

    }
}
package org.example.lambda;

public class LambdaTest {

    @FunctionalInterface
    interface TestLambda1{
        void testLambda();

    }

//    public static void main(String[] args) {
//      //没有返回值的Lambda表达式
//        TestLambda1 testLambda1=()->{
//            System.out.println("hello,testLambda1");
//        };
//        testLambda1.testLambda();// hello,testLambda1
//
//        //如果在执行代码块中,只有一行代码,大括号是可以省略的
//        TestLambda1 testLambda2=()-> System.out.println("hello,testLambda2");;
//        testLambda2.testLambda();// hello,testLambda2
//
//
//    }

    @FunctionalInterface
    interface TestLambda2 {
        void test(String name, int age);
    }

//    public static void main(String[] args) {
//        //带有参数 但是没有返回值得Lambda表达式和接口
//        //带有参数时,要将参数写在小括号中,参数的顺序和接口中定义的顺序相同
//        TestLambda2 testLambda1 =(String name, int age)->{
//            System.out.println(name+"今年"+age+"岁了");
//        };
//        testLambda1.test("庞鹏程",21);//庞鹏程今年21岁了
//
//        //在设置参数时,也可以不写参数的类型,JVM会自动推断出参数的类型,以下方式和上面的代码是一样的
//        TestLambda2 testLambda2 =(name, age)->{
//            System.out.println(name+"今年"+age+"岁了");
//        };
//        testLambda1.test("庞鹏程",21);//庞鹏程今年21岁了
//
//    }

    @FunctionalInterface
    interface TestLambda3 {
        int test(int x, int y);
    }

    public static void main(String[] args) {
        //带有参数,带有返回值的Lambda表达式
        TestLambda3 testLambda1 = (x,y)->{
            int z =x+y;
            return z;
        };
        System.out.println(testLambda1.test(6, 12));//18

        //当花括号内只有一行代码时,可以不添加花括号,同时,也不需要添加 return 关键字,虚拟机会自动帮你返回
        TestLambda3 testLambda2 =(x,y)-> x+y;
        System.out.println(testLambda2.test(6, 12));//18

    }

}

总结

1 Lambda 表达式,必须和接口进行绑定

2 Lambda 表达式的参数,可以附带0到n个参数,括号中的参数类型可以不用指定,JVM在运行时,会自动根据绑定的抽象方法进行推导

3 Lambda 表达式的返回值,如果代码快只有一行并且没有大括号,不用写大括号,单行代码会自动返回,如果添加了大括号,或者代码有多行代码,必须通过return 关键字返回结果

变量访问

package org.example.lambda;

/**
 * 变量捕获-变量的访问操作
 */
public class VariableCapture {
    String s1 = "全局变量";

    // 1. 匿名内部类型中对于变量的访问
    public void testInnerClass() {
        String s2 = "局部变量";

        new Thread(new Runnable() {
            String s3 = "内部变量";
            @Override
            public void run() {
                // 访问全局变量
                /**
                 * System.out.println(this.s1);this关键字~表示是当前内部类型的对象,故全局变量不能通过this关键字访问
                 */
                System.out.println(s1); // 全局变量

                /**
                 * 局部变量的访问,~不能对局部变量进行数据的修改[final]
                 */
                System.out.println(s2);// 局部变量
                //s2 = "hello";


                /**
                 * 访问内部变量,是可以通过this关键字访问的,this关键字~表示是当前内部类型的对象
                 */
                System.out.println(s3); // 内部变量
                System.out.println(this.s3);  内部变量

            }
        }).start();
    }

    // 2. lamdba表达式对于变量的访问
    public void testLambda() {
        String s2 = "局部变量lambda";

        new Thread(() -> {
            String s3 = "内部变量lambda";

            /**
             * 访问全局变量 在Lambda中是允许通过this关键字访问全局变量的,因为this关键字,表示的就是所属方法所在类型的对象
             *  在使用了Lambda中,this关键字表示的就是所属方法所在类型的对象
             */
            System.out.println(this.s1);// 全局变量
            // 访问局部变量
            System.out.println(s2);     // 局部变量lambda
            //s2 = "hello";// 不能进行数据修改,默认推导变量的修饰符:final
            System.out.println(s3);     //  内部变量lambda
            s3 = "lambda 内部变量直接修改";
            System.out.println(s3);      // lambda 内部变量直接修改
        }).start();
    }

    public static void main(String[] args) {
        VariableCapture variableCapture = new VariableCapture();
        variableCapture.testInnerClass();
        variableCapture.testLambda();

    }
}

Lambda表达式的变量操作,优化了匿名内部类的this关键字,不在单独建立对象作用域。表达式本身就是所属类型对象的一部分,在语法语义上使用更加简洁

Lambda表达式类型检查

表达式类型检查

定义一个函数式接口 MyInterface,接收两个范型T,R,并提供一个方法 strategy 接受参数T 返回参数R

public class TypeCheck {

    /**
     * 定义一个函数式接口 MyInterface,接收两个范型T,R,并提供一个方法 strategy 接受参数T 返回参数R
     * @param <T>
     * @param <R>'
     */
    //定义函数式接口MyInterface
    @FunctionalInterface
    interface MyInterface<T,R>{
        R strategy(T t, R r);
    }

    //定义一个方法test,接受一个MyInterface作为参数,范型为String 和List,在方法内部我们将String 添加到List集合中
    public static void test(MyInterface<String, List> inter) {
        List<String> list = inter.strategy("hello", new ArrayList());
        System.out.println(list);
    }

    public static void main(String[] args) {
        //使用匿名内部类的方式调用test
        test(new MyInterface<String, List>() {
            @Override
            public List strategy(String s, List list) {
                list.add(s);
                return list; //[hello]
            }
        });

        //使用Lambda表达式的方式调用test
        /**
         * 在Lambda表达式的写法中,并没有指明方法的参数为MyInterface,
         * 而是直接传递了参数X,y,这是由底层虚拟机来自动推导出来的。
         */
        test((x, y) -> {
            y.add(x);
            return y; // [hello]
//            x.add(y);
//            return x;
        });


    }
}

在Lambda表达式的写法中,并没有指明方法的参数为Myinterface,而是直接传递了参数x,y,这是由底层虚拟机来自动推导出来的。总结当我们使用Lambda表达式语法的时候,jvm会获取当前方法的参数来进行推导,从而自动为我们绑定方法的参数类型.这就是Lambda表达式的类型检查

方法重载和Lambda表达式

首先创建一个类LambdaTest类,在LambdaTest类中创建两个接口 Parame1 和Parame2,并定义outInfo(String info) 方法

然后定义重载方法lambdaMethod,参数分别是Parame1和Parame2

使用传统的匿名内部类的方式调用,在main方法中创建App4的对象,使用对象点lambdaMethdo的方式new一个Parame1或者Parame2

使用lambda表达式的话因为是重载方法,jvm自动推导类型的时候类型检查不通过,会报如下错误

在这种情况下只能使用匿名内部类来替代lambda表达式

深入理解Lambda表达式

Lambda表达式低层解析运行原理

创建一个类App,并创建一个用于Lambda表达式执行的函数式接口IMakeUP,提供一个方法makeUp(String msg),在main方法中创建Lambda表达式打印msg

将App.java文件编译(编译java文件命令 javac 文件名)后,我们可以看到生成了App.class文件和IMakeUP.class文件

通过使用 javap -p App.class 命令对class文件进行反编译得到结果

Lambda表达式在JVM低层解析成私有静态方法和匿名内部类型

通过实现接口的匿名内部类型中接口方法调用静态实现方法,完成Lambda表达式的执行

方法引用

  • 方法引用是结合Lambda表达式的一种语法特性,是用来简化代码书写的,但是代码可读性差,本质就是简化方法的调用方式 静态方法引用 实例方法引用 构造方法引用

Demo

首先创建一个测试类MethodReference, 在里面创建一个内部类Person,添加属性 name(名字),gender(性别),age(年龄),并使用lombok创建get/set方法和构造函数

package org.example.method;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class MethodReference {
    public static void main(String[] args) {
        //存储Person对象的列表  初始化一些数据,并对数据进行排序
        List<Person> personList = new ArrayList<>();
        personList.add(new Person("tom", "男", 16));
        personList.add(new Person("jerry", "女", 15));
        personList.add(new Person("ppc", "男", 30));
        personList.add(new Person("cxk", "女", 26));
        personList.add(new Person("kuLi", "男", 32));
        System.out.println(personList);
        /**
         * [
         *    Person(name=tom, gender=男, age=16),
         *    Person(name=jerry, gender=女, age=15),
         *    Person(name=ppc, gender=男, age=30),
         *    Person(name=cxk, gender=女, age=26),
         *    Person(name=kuLi, gender=男, age=32)
         *    ]
         */
        //匿名内部类实现方式--列表排序
        Collections.sort(personList, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
               return o1.getAge() - o2.getAge();
            }
        });
        System.out.println(personList);
        /**
         * [
         *    Person(name=jerry, gender=女, age=15),
         *    Person(name=tom, gender=男, age=16),
         *    Person(name=cxk, gender=女, age=26),
         *    Person(name=ppc, gender=男, age=30),
         *    Person(name=kuLi, gender=男, age=32)
         *   ]
         */
        //lambda表达式实现
        Collections.sort(personList, (p1,p2) -> p1.getAge()-p2.getAge());
        System.out.println("===========");
        System.out.println(personList);
        /**
         * [
         *  Person(name=jerry, gender=女, age=15),
         *  Person(name=tom, gender=男, age=16),
         *  Person(name=cxk, gender=女, age=26),
         *  Person(name=ppc, gender=男, age=30),
         *  Person(name=kuLi, gender=男, age=32)
         *  ]
         */
        /**
         * 静态方法引用的使用
         * 类型名称.方法名称() ---> 类型名称::方法名称
         */
        Collections.sort(personList, Person::compareByAge); //compareByAge是一个静态方法
        System.out.println(personList);
        /**
         * [  Person(name=kuLi, gender=男, age=32),
         *    Person(name=ppc, gender=男, age=30),
         *    Person(name=cxk, gender=女, age=26),
         *    Person(name=tom, gender=男, age=16),
         *    Person(name=jerry, gender=女, age=15)]
         */
        System.out.println("===========");

        /**
         * 实例方法引用的使用
         * 类型名称.实例方法名称() ---> 类型名称::实例方法名称
         */
        PersonUtil pu = new PersonUtil();
        Collections.sort(personList,pu::compareByName);
        System.out.println("tom".hashCode()); //115026
        System.out.println("jerry".hashCode());  //115026
        System.out.println(personList);
        /**
         * [  Person(name=cxk, gender=女, age=26),
         *    Person(name=ppc, gender=男, age=30),
         *    Person(name=tom, gender=男, age=16),
         *    Person(name=kuLi, gender=男, age=32),
         *    Person(name=jerry, gender=女, age=15)
         *   ]
         */

        /**
         * 构造方法的引用使用
         * 类型对象的构造过程 ---> 类型名称::new
         */
        IPerson ip = Person::new;
        Person person = ip.initPerson("ppc", "male", 21);
        System.out.println(person); //Person(name=ppc, gender=male, age=21)

    }

}

@Data
@NoArgsConstructor
@AllArgsConstructor
class Person {
    private String name;    // 姓名
    private String gender;  // 性别
    private int age;        // 年龄

    //静态方法
    public static int compareByAge(Person p1, Person p2) {
        return p2.getAge() - p1.getAge();
    }
}

class PersonUtil {
    // 增加一个实例方法
    public int compareByName(Person p1, Person p2) {
        return p1.getName().hashCode() - p2.getName().hashCode();
    }
}
//构造方法引用,构造方法的引用需要绑定一个函数式接口,首先创造一个函数式接口
interface IPerson {
    // 抽象方法:通过指定类型的构造方法初始化对象数据
    Person initPerson(String name, String gender, int age);
}

构造方法引用

构造方法的引用需要绑定一个函数式接口,首先创造一个函数式接口

实例方法引用

创建类型对应的对象 -->对象引用::实例方法名称

MethodReference下创建一个新类PersonUtils,添加一个方法comerByName(),根据人员的名称的hash值来进行排序

静态方法引用

类型名称::方法名称

Stream概述

什么是Stream?

Stream是Java为了操作数组,集合来进行复杂的聚合操作而推出的一套新的API

新创建一个测试类TestStream 创建一个main方法,在main方法中初始化一个字符串集合

package org.example.TestStream;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

public class TestStream {
    public static void main(String[] args) {
        /**
         * 1. 添加测试数据:存储多个账号的列表
         */
        List<String> accounts = new ArrayList<String>();
        accounts.add("tom");
        accounts.add("ppc");
        accounts.add("kuLi");
        accounts.add("keBi");
        accounts.add("zhanMuSi");
        System.out.println(accounts); //[tom, ppc, kuLi, keBi, zhanMuSi]
        /**
         * 业务要求:要求从存储多个账号的列表中选出长度大于等于5的有效账号
         */
        // 1.循环方式
        for (String account : accounts) {
            if (account.length() >= 5) {
                System.out.println("有效账号:"  + account); //有效账号:zhanMuSi
            }
        }

        // 2.迭代器方式
        Iterator<String> it = accounts.iterator();
        while(it.hasNext()) {
            String account = it.next();
            if (account.length() >=5) {
                System.out.println("有效账号:" + account); //有效账号:zhanMuSi

            }
        }

        // 3.使用Steam结合Lambda表达式的方式,完成业务处理
        List<String> validAccounts = accounts.stream().filter(s -> s.length() >= 5).collect(Collectors.toList());
        System.out.println(validAccounts); //[zhanMuSi]

    }
}

注意:这三种方式的性能是相同的,只是精简了代码长度

SteamAPI

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

YOLOv8 多目标跟踪

文章大纲 简介环境搭建代码样例跟踪原理代码分析原始老版实现新版本封装代码实现追踪与计数奇奇怪怪错误汇总lap 安装过程报错推理过程报错参考文献与学习路径简介 使用yolov8 做多目标跟踪 文档地址: https://docs.ultralytics.com/modes/track/https://github.com/ultralyt…

【多线程】多线程案例

✨个人主页&#xff1a;bit me&#x1f447; ✨当前专栏&#xff1a;Java EE初阶&#x1f447; ✨每日一语&#xff1a;we can not judge the value of a moment until it becomes a memory. 目 录&#x1f35d;一. 单例模式&#x1f364;1. 饿汉模式实现&#x1f9aa;2. 懒汉模…

java如何创建线程

java如何创建线程1. java如何创建线程1.1 通过继承Thread类来创建线程1.2 通过实现Runnable接口来创建线程1.3 通过匿名内部类来创建线程1.4 lambda表达式1.5 通过实现Runnable接口的方式创建线程目标类的优缺点1. java如何创建线程 一个线程在Java中使用一个Thread实例来描述…

android8 rk3399 同时支持多个USB摄像头

文章目录一、前文二、CameraHal_Module.h三、CameraHal_Module.cpp四、编译&烧录Image五、App验证一、前文 Android系统默认支持2个摄像头&#xff0c;一个前置摄像头&#xff0c;一个后置摄像头需要支持数量更多的摄像头&#xff0c;得修改Android Hal层的代码 二、Camer…

VueX快速入门(适合后端,无脑入门!!!)

文章目录前言State和Mutations基础简化gettersMutationsActions&#xff08;异步&#xff09;Module总结前言 作为一个没啥前端基础&#xff08;就是那种跳过js直接学vue的那种。。。&#xff09;的后端选手。按照自己的思路总结了一下对VueX的理解。大佬勿喷qAq。 首先我们需要…

我的 System Verilog 学习记录(11)

引言 本文简单介绍 SystemVerilog 的其他程序结构。 前文链接&#xff1a; 我的 System Verilog 学习记录&#xff08;1&#xff09; 我的 System Verilog 学习记录&#xff08;2&#xff09; 我的 System Verilog 学习记录&#xff08;3&#xff09; 我的 System Verilo…

Linux lvm管理讲解及命令

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a;小刘主页 ♥️每天分享云计算网络运维课堂笔记&#xff0c;努力不一定有收获&#xff0c;但一定会有收获加油&#xff01;一起努力&#xff0c;共赴美好人生&#xff01; ♥️夕阳下&#xff0c;是最美的绽放&#xff0…

软件行业的最后十年【ChatGPT】

在这篇文章中&#xff0c;我将说明像 ChatGPT 这样的生成式人工智能 (GAI) 将如何在十年内取代软件工程师。 预测被离散化为 5 个阶段&#xff0c;总体轨迹趋向于完全接管。 但首先&#xff0c;一个简短的前言。 推荐&#xff1a;用 NSDT场景设计器 快速搭建3D场景。 1、关于AI…

二叉搜索树:AVL平衡

文章目录一、 二叉搜索树1.1 概念1.2 操作1.3 代码实现二、二叉搜索树的应用K模型和KV模型三、二叉搜索树的性能分析四、AVL树4.1 AVL树的概念4.2 AVL树的实现原理4.3 旋转4.4 AVL树最终代码一、 二叉搜索树 1.1 概念 二叉搜索树&#xff08; Binary Search Tree&#xff0c;…

LeetCode刷题记录---数位DP算法

😄 学会数位dp算法,可以连杀好几道力扣困难题,加油~ 🚀题目: 难度题目困难2376. 统计特殊整数困难1012. 至少有 1 位重复的数字困难233. 数字 1 的个数困难面试题 17.06. 2出现的次数🚀学习资料: 数位dp算法,我是跟着灵神学的,感谢灵神!数位 dp 通用模板参考灵神…

Python数据分析案例24——基于深度学习的锂电池寿命预测

本期开始案例较为硬核起来了&#xff0c;适合理工科的硕士&#xff0c;人文社科的同学可以看前面的案例。 案例背景 这篇文章是去年就发了&#xff0c;刊物也印刷了&#xff0c;现在分享一部分代码作为案例给需要的同学。 原文链接&#xff08;知网文章 C核&#xff09;&…

python如何快速采集美~女视频?无反爬

人生苦短 我用python~ 这次康康能给大家整点好看的不~ 环境使用: Python 3.8 Pycharm mou歌浏览器 mou歌驱动 —> 驱动版本要和浏览器版本最相近 <大版本一样, 小版本最相近> 模块使用: requests >>> pip install requests selenium >>> pip …

不是,到底有多少种图片懒加载方式?

一、也是我最开始了解到的 js方法&#xff0c;利用滚动事件&#xff0c;判断当时的图片位置是否在可视框内&#xff0c;然后进行渲染。 弊端&#xff1a;代码冗杂&#xff0c;你还要去监听页面的滚动事件&#xff0c;这本身就是一个不建议监听的事件&#xff0c;即便是我们做了…

【selenium学习】数据驱动测试

数据驱动在 unittest 中&#xff0c;使用读取数据文件来实现参数化可以吗&#xff1f;当然可以。这里以读取 CSV文件为例。创建一个 baidu_data.csv 文件&#xff0c;如图所示&#xff1a;文件第一列为测试用例名称&#xff0c;第二例为搜索的关键字。接下来创建 test_baidu_da…

百度生成式AI产品文心一言邀你体验AI创作新奇迹:百度CEO李彦宏详细透露三大产业将会带来机遇(文末附文心一言个人用户体验测试邀请码获取方法,亲测有效)

百度生成式AI产品文心一言邀你体验AI创作新奇迹中国版ChatGPT上线发布强大中文理解能力超强的数理推算能力智能文学创作、商业文案创作图片、视频智能生成中国生成式AI三大产业机会新型云计算公司行业模型精调公司应用服务提供商总结获取文心一言邀请码方法中国版ChatGPT上线发…

贪心算法的原理以及应用

文章目录0、概念0.1.定义0.2.特征0.3.步骤0.4.适用1、与动态规划的联系1.1.区别1.2.联系2、例子3、总结4、引用0、概念 0.1.定义 贪心算法&#xff08;greedy algorithm &#xff0c;又称贪婪算法&#xff09;是指&#xff0c;在对问题求解时&#xff0c;总是做出在当前看来是…

Java怎么实现几十万条数据插入(30万条数据插入MySQL仅需13秒)

本文主要讲述通过MyBatis、JDBC等做大数据量数据插入的案例和结果。 30万条数据插入插入数据库验证实体类、mapper和配置文件定义User实体mapper接口mapper.xml文件jdbc.propertiessqlMapConfig.xml不分批次直接梭哈循环逐条插入MyBatis实现插入30万条数据JDBC实现插入30万条数…

第十九天 Maven总结

目录 Maven 1. 前言 2. 概述 2.1 介绍 2.2 安装 3. IDEA集成Maven 3.1 集成Maven环境 3.2 创建Maven项目 3.3 Maven坐标详解 3.4 导入maven项目 4. 依赖管理 4.1 依赖配置 4.2 依赖传递 4.3 依赖范围 4.4 生命周期 4.5 插件 Maven 1. 前言 1). 什么是Maven? …

Linux实操之服务管理

文章目录一、服务(service)管理介绍:service管理指令查看服务名服务的运行级别(runlevel):CentOS7后运行级别说明chkconfig指令介绍一、服务(service)管理介绍: 服务(service)本质就是进程&#xff0c;但是是运行在后台的&#xff0c;通常都会监听某个端口&#xff0c;等待其它…

原力计划来了【协作共赢 成就未来】

catalogue&#x1f31f; 写在前面&#x1f31f; 新星计划持续上新&#x1f31f; 原力计划方向&#x1f31f; 原力计划拥抱优质&#x1f31f; AIGC&#x1f31f; 参加新星计划还是原力计划&#x1f31f; 创作成就未来&#x1f31f; 写在最后&#x1f31f; 写在前面 哈喽&#x…
最新文章