当前位置: 首页 > news >正文

原来Lambda表达式是这样写的

原来Lambda表达式是这样写的

lambda 是一个匿名函数,我们可以把 lambda 表达式理解为是一段可以传递的代码。

lambda 简明地将代码或方法作为参数传递进去执行。

函数式编程:核心是把函数作为值。

函数式接口 :只有一个抽象方法的接口称之为函数式接口。

函数式接口可以使用@FunctionalInterface进行注解。

lambda表达式拆分为两部分:

  • 左侧:lambda 表达式的参数列表

  • 右侧:lambda 表达式中所需要执行的功能,即 lambda 体

Lambda 表达式非常方便,在项目中一般在 stream 编程中用的比较多。

package com.lambda;import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;public class Test1 {public static void main(String[] args) {List<Student> studentList = new ArrayList<>();studentList.add(new Student(1, "tom"));studentList.add(new Student(2, "marry"));// Collectors.toMap的用法有很多Map<Integer, String> map = studentList.stream().collect(Collectors.toMap(Student::getId, Student::getName));// {1=tom, 2=marry}System.out.println(map);}}class Student {private int id;private String name;public Student() {}public Student(int id, String name) {this.id = id;this.name = name;}public int getId() {return id;}public String getName() {return name;}public void setId(int id) {this.id = id;}public void setName(String name) {this.name = name;}
}

理解一个 Lambda 表达式就三步:

1、确认 Lambda 表达式的类型

2、找到要实现的方法

3、实现这个方法

就这三步,没其他的了。

1、确认 Lambda 表达式的类型

能用 Lambda 表达式来表示的类型,必须是一个函数式接口,而函数式接口,就是只有一个抽象方法的接口。

例如 JDK 中 Runnable 接口:

@FunctionalInterface
public interface Runnable {public abstract void run();
}

这就是一个标准的函数式接口,因为只有一个抽象方法,而且这个接口上有个注解 @FunctionalInterface

这个仅仅是在编译期帮你检查你这个接口是否符合函数式接口的条件,比如你没有任何抽象方法,或者有多个抽象

方法,编译是无法通过的。

再稍稍复杂一点,Java 8 之后接口中是允许使用默认方法静态方法的,而这些都不算抽象方法,所以也可以加在

函数式接口里。看看你可能不太熟悉又有点似曾相识的一个接口。

@FunctionalInterface
public interface Consumer<T> {void accept(T t);default Consumer<T> andThen(Consumer<? super T> after) {}
}

只有一个抽象方法,还有一个默认方法(方法体的代码省略了),这个也不影响它是个函数式接口。再看一个更复杂

的,多了静态方法,这同样也是个函数式接口,因为它仍然只有一个抽象方法。

@FunctionalInterface
public interface Predicate<T> {boolean test(T t);default Predicate<T> and(Predicate<? super T> other) {...}default Predicate<T> negate() {...}default Predicate<T> or(Predicate<? super T> other) {...}static <T> Predicate<T> isEqual(Object targetRef) {...}static <T> Predicate<T> not(Predicate<? super T> target) {...}
}

先不用管这些方法都是干嘛的,这些类在 Stream 设计的方法中比比皆是,我们就先记住这么一句话,Lambda表

达式需要的类型为函数式接口,函数式接口里只有一个抽象方法,就够了,以上三个例子都属于函数式接口。

2、找到要实现的方法

Lambda 表达式就是实现一个方法,什么方法呢?就是刚刚那些函数式接口中的抽象方法。

那就太简单了,因为函数式接口有且只有一个抽象方法,找到它就行了。我们尝试把刚刚那几个函数式接口的抽象

方法找到。

@FunctionalInterface
public interface Runnable {public abstract void run();
}@FunctionalInterface
public interface Consumer<T> {void accept(T t);default Consumer<T> andThen(Consumer<? super T> after) {...}
}@FunctionalInterface
public interface Predicate<T> {boolean test(T t);default Predicate<T> and(Predicate<? super T> other) {...}default Predicate<T> negate() {...}default Predicate<T> or(Predicate<? super T> other) {...}static <T> Predicate<T> isEqual(Object targetRef) {...}static <T> Predicate<T> not(Predicate<? super T> target) {...}
}

3、实现这个方法

Lambda 表达式就是要实现这个抽象方法,如果不用 Lambda 表达式,你一定知道用匿名类如何去实现吧?比如

我们实现刚刚 Predicate 接口的匿名类。

Predicate<String> predicate = new Predicate<String>() {@Overridepublic boolean test(String s) {return s.length() != 0;}
};

3.1 单个入参

那如果换成 Lambda 表达式呢?就像这样。

Predicate<String> predicate = (String s) -> {return s.length() != 0;
};

看出来了么?这个 Lambda 语法由三部分组成:

1、参数块:就是前面的 (String s),就是简单地把要实现的抽象方法的参数原封不动写在这。

2、小箭头:就是 -> 这个符号。

3、代码块:就是要实现的方法原封不动写在这。

首先看参数快部分,(String s) 里面的类型信息是多余的,因为完全可以由编译器推导,去掉它。

注意:lambda 表达式的参数类型可以省略不写,因为 jvm 编译器可以从上下文推断出数据类型。

即“类型推断”如果要在参数里面写数据类型,都要写上。

Predicate<String> predicate = (s) -> {return s.length() != 0;
};

当只有一个参数时,括号也可以去掉。

Predicate<String> predicate = s -> {return s.length() !=0;
};

再看代码块部分,方法体中只有一行代码,可以把花括号和 return 关键字都去掉。

Predicate<String> p = s -> s.length() != 0;

3.2 无入参

来,再让我们实现一个 Runnable 接口。

@FunctionalInterface
public interface Runnable {public abstract void run();
}
Runnable r = () -> System.out.println("I am running");

你看,这个方法没有入参,所以前面括号里的参数就没有了,这种情况下括号就不能省略。

通常我们快速新建一个线程并启动时,是不是像如下的写法,熟悉吧?

new Thread(() -> System.out.println("I am running")).start();

3.3 多个入参

之前我们只尝试了一个入参,接下来我们看看多个入参的。

@FunctionalInterface
public interface BiConsumer<T, U> {void accept(T t, U u);
}

然后看看一个用法,是不是一目了然。

BiConsumer<Random, Integer> randomNumberPrinter = (random, number) -> {for (int i = 0; i < number; i++) {System.out.println("next random = " + random.nextInt());}
};
randomNumberPrinter.accept(new Random(314L), 5);

3.4 带返回值

刚刚只是多个入参,那我们再加个返回值:

@FunctionalInterface
public interface BiFunction<T, U, R> {R apply(T t, U u);
}
BiFunction<String, String, Integer> findWordInSentence =(word, sentence) -> sentence.indexOf(word);
Integer result = findWordInSentence.apply("e","hello");
// 1
System.out.println(result);

4、四大核心函数式接口

其实函数式接口里那个抽象方法,无非就是入参的个数,以及返回值的类型。入参的个数可以是一个或者两个,返

回值可以是 void,或者 boolean,或者一个类型。那这些种情况的排列组合,就是 JDK 给我们提供的

java.util.function 包下的类。

别看晕了,我们分分类就好了。可以注意到很多类前缀是 Int,Long,Double 之类的,这其实是指定了入参的特

定类型,而不再是一个可以由用户自定义的泛型,比如说 DoubleFunction。

@FunctionalInterface
public interface DoubleFunction<R> {R apply(double value);
}

这完全可以由更自由的函数式接口 Function 来实现。

@FunctionalInterface
public interface Function<T, R> {R apply(T t);
}

函数式接口几个简单分类就是:

supplier: 没有入参,有返回值。

function: 有入参,有返回值。

consumer: 有入参,无返回值。

predicate: 有入参,返回 boolean 值。

Consumer: 消费性接口,void accept(T t)。

Supplier: 共给性接口,T get()。

Function<T,R>: 函数性接口,T代表参数,R代表返回值,R apply(T t)。

Predicate: 断言性接口,boolean test(T t)。

其实就是给我们提供了一个函数的模板,区别仅仅是入参返参个数的排列组合。

package com.lambda;import java.util.function.Consumer;public class Test2 {public static void main(String[] args) {happy(10000, (money) -> System.out.println("happy消费" + money + "元"));}public static void happy(double money, Consumer<Double> con) {con.accept(money);}
}

5、Stream编程

下面这段代码如果你项目中有用 stream 编程那肯定很熟悉,有一个 Student 的 list,你想把它转换成一个 map,

key 是 student 对象的 id,value 就是 student 对象本身。

package com.lambda;import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;public class Test3 {public static void main(String[] args) {List<Student> studentList = new ArrayList<>();studentList.add(new Student(1, "tom"));studentList.add(new Student(2, "marry"));// Collectors.toMap的用法有很多Map<Integer, Student> map = studentList.stream().collect(Collectors.toMap(Student::getId, a -> a, (a, b) -> a));// {1=com.lambda.Student@2f4d3709, 2=com.lambda.Student@4e50df2e}System.out.println(map);}
}

把 Lambda 表达式的部分提取出来。

Collectors.toMap(Student::getId, a -> a, (a, b) -> a)

由于我们还没见过 :: 这种形式,先打回原样,这里只是让你预热一下。

Collectors.toMap(a -> a.getId(), a -> a, (a, b) -> a)

为什么它被写成这个样子呢?我们看下 Collectors.toMap 这个方法的定义就明白了。

public static <T, K, U>
Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,Function<? super T, ? extends U> valueMapper,BinaryOperator<U> mergeFunction) {return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);
}

看,入参有三个,分别是 Function,Function,BinaryOperator,其中 BinaryOperator 只是继承了 BiFunction

并扩展了几个方法,我们没有用到,所以不妨就把它当做 BiFunction。还记得 Function 和 BiFunction 吧?

Function R apply(T t)
BiFunction R apply(T t, U u)

第一个参数 a -> a.getId() 就是 R apply(T t) 的实现,入参是 Student 类型的对象 a,返回 a.getId()。

第二个参数 a -> a 也是 R apply(T t) 的实现,入参是 Student 类型的 a,返回 a 本身。

第三个参数 (a, b) -> a 是 R apply(T t, U u) 的实现,入参是Student 类型的 a 和 b,返回是第一个入参 a,

Stream 里把它用作当两个对象 ,a 和 b 的 key 相同时,value 就取第一个元素 a,其中第二个参数 a -> a 在

Stream 里表示从 list 转为 map 时的 value 值,就用原来的对象自己,你肯定还见过这样的写法。

Collectors.toMap(a -> a.getId(), Function.identity(), (a, b) -> a)

为什么可以这样写,给你看 Function 类的全貌你就明白了。

@FunctionalInterface
public interface Function<T, R> {R apply(T t);default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {Objects.requireNonNull(before);return (V v) -> apply(before.apply(v));}default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {Objects.requireNonNull(after);return (T t) -> after.apply(apply(t));}static <T> Function<T, T> identity() {return t -> t;}
}

看到了吧,identity 这个方法,就是帮我们把表达式给实现了,就不用我们自己写了,其实就是包了个方法。这回

知道一个函数式接口,为什么有好多还要包含一堆默认方法和静态方法了吧?就是干这个事用的。

我们再来试一个,Predicate 里面有这样一个默认方法 and。

@FunctionalInterface
public interface Predicate<T> {boolean test(T t);default Predicate<T> and(Predicate<? super T> other) {Objects.requireNonNull(other);return (t) -> test(t) && other.test(t);}default Predicate<T> negate() {return (t) -> !test(t);}default Predicate<T> or(Predicate<? super T> other) {Objects.requireNonNull(other);return (t) -> test(t) || other.test(t);}static <T> Predicate<T> isEqual(Object targetRef) {return (null == targetRef)? Objects::isNull: object -> targetRef.equals(object);}
}

它能干嘛用呢?我来告诉你,如果没有这个方法,有一段代码你可能会这样写。

Predicate<String> p = s -> (s != null) && !s.isEmpty() && s.length() < 5;

如果利用上这个方法,就可以变成如下这种优雅形式。

Predicate<String> nonNull = s -> s != null;
Predicate<String> nonEmpty = s -> s.isEmpty();
Predicate<String> shorterThan5 = s -> s.length() < 5;
Predicate<String> p = nonNull.and(nonEmpty).and(shorterThan5);

6、Lambda方法引用

主要有三种语法格式:

对象::实例方法名

类::静态方法名

类::实例方法名

那我们回过头再看刚刚的 Student::getId 这种写法。当方法体中只有一个方法调用时,就可以作这样的简化。

比如这个 a -> a.getId() 就只是对 Student 对象上 getId() 这个方法的调用,那么就可以写成 Student::getId 这种形

式。

package com.lambda;import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;public class Test9 {public static void main(String[] args) {// 类::实例方法名Function<User, String> n = User::getName;Function<User, Integer> a = User::getAge;// 类::静态方法名Function<String, String> func1 = User::concat2;Supplier<String> func2 = User::getAddress;// 对象::实例方法名User user = new User();Function<String, String> func3 = user::concat1;Supplier<String> func4 = user::getSchool;// 无参构造方法引用Supplier<Student> supplier = Student::new;Student student = supplier.get();student.setName("tom");student.setId(10);// com.lambda.Student@5b480cf9System.out.println(student);Supplier<Student> supplier2 = () -> (new Student());Student student2 = supplier2.get();student2.setName("tom");student2.setId(10);// com.lambda.Student@723279cfSystem.out.println(student2);// 有参构造方法引用BiFunction<Integer, String, Student> biFunction = Student::new;Student stu = biFunction.apply(11, "marry");// com.lambda.Student@b4c966aSystem.out.println(stu);BiFunction<Integer, String, Student> bf = (id, name) -> new Student(id, name);Student s = bf.apply(12, "john");// com.lambda.Student@4e50df2eSystem.out.println(s);// 自定义有参构造函数StudentBuilder sb1 = ((id, name) -> new Student(id, name));Student s1 = sb1.build(13, "xm");// com.lambda.Student@7cc355beSystem.out.println(s1);StudentBuilder sb2 = Student::new;Student s2 = sb2.build(14, "xh");// com.lambda.Student@12edcd21System.out.println(s2);// 自定义无参构造函数StudentBuilderNoArgs sb3 = Student::new;Student s3 = sb3.build();// com.lambda.Student@5b6f7412System.out.println(s3);StudentBuilderNoArgs sb4 = () -> (new Student());Student s4 = sb4.build();// com.lambda.Student@312b1daeSystem.out.println(s4);}
}class User {private static int id;private String name;public static int getId() {return id;}public static void setId(int id) {User.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String concat1(String str) {return str + "!";}public static String concat2(String str) {return str + "!";}public int getAge() {return 12;}public static String getAddress() {return "天津";}public String getSchool() {return "小学";}
}interface StudentBuilder {Student build(int id, String name);
}interface StudentBuilderNoArgs {Student build();
}

再看几个例子:

Function<String, Integer> toLength1 = s -> s.length();
Function<String, Integer> toLength2 = String::length;
Function<User, String> getName = user -> user.getName();
Function<User, String> toLength = User::getName;

如果是构造方法的话,也可以简化。

Supplier<List<String>> newListOfStrings1 = () -> new ArrayList<>();
Supplier<List<String>> newListOfStrings2 = ArrayList::new;
// ClassName::new
Supplier<String> sup = () -> new String();
Supplier<String> sup2 = String::new;
String str = sup.get();
String str2 = sup2.get();
// false
System.out.println(str == str2);
// 对象::实例方法名
Consumer<String> con = (x) -> System.out.println(x);
con.accept("hello");
Consumer<String> con2 = System.out::println;
con2.accept("world");
// 类::静态方法名
Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
Comparator<Integer> com2 = Integer::compare;
System.out.println(com.compare(1, 2));
System.out.println(com2.compare(1, 2));
// 类::实例方法名
BiPredicate<String, String> bp = (x, y) -> x.equals(y);
System.out.println(bp.test("a", "a"));
BiPredicate<String, String> bp2 = String::equals;
System.out.println(bp2.test("a", "a"));

7、Lambda例子

实例1:

package com.lambda;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class Test6 {public static List<Employee> list = Arrays.asList(new Employee("张三", 10, 1), new Employee("里斯", 20, 1), new Employee("王五", 16, 1), new Employee("二三", 30, 1));public static List<Employee> filterEmployee(List<Employee> list, MyPredicate<Employee> mp) {List<Employee> emps = new ArrayList<>();for (Employee employee : list) {if (mp.test(employee)) {emps.add(employee);}}return emps;}public static void main(String[] args) {test1();test2();}public static void test1() {//需要使用自定义的方法List<Employee> list2 = filterEmployee(list, (e) -> e.getAge() >= 15);list2.stream().map(Employee::getName).forEach(System.out::println);}public static void test2() {//可以使用stream进行list集合的过滤  不使用自定义接口List<Employee> list2 = list.stream().filter((e) -> e.getAge() >= 15).collect(Collectors.toList());list2.stream().map(Employee::getName).forEach(System.out::println);}
}class Employee {private String name;private int age;private double salary;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public double getSalary() {return salary;}public void setSalary(double salary) {this.salary = salary;}public Employee(String name, int age, double salary) {this.name = name;this.age = age;this.salary = salary;}
}interface MyPredicate<T> {boolean test(T t);
}
# 程序输出
里斯
王五
二三
里斯
王五
二三

实例2:

创建一个MyFun接口使用@FunctionalInterface注解,并创建一个抽象方法Integer getValue(Integer num);在

Test类对变量进行某种操作。

package com.lambda;@FunctionalInterface
interface MyFun {Integer getValue(Integer num);
}public class Test7 {public static void test() {int a = 10;System.out.println(a);a = operation(a, num -> ++num);System.out.println(a);}public static void main(String[] args) {test();}/*** param1 num : 传入的整形数* param2 mf : 实现某种方式对 整形数 进行操作。**/public static Integer operation(Integer num, MyFun mf) {return mf.getValue(num);}
}
# 程序输出
10
11
package com.lambda;import java.util.Arrays;
import java.util.Collections;
import java.util.List;public class Test8 {public static List<Employee> list = Arrays.asList(new Employee("张三", 10, 1),new Employee("里斯", 20, 1),new Employee("王五", 16, 1),new Employee("二三", 30, 1));public static void test() {Collections.sort(list, (e1, e2) -> {if (e1.getAge() == e2.getAge()) {return e1.getName().compareTo(e2.getName());} else {//比较年龄大小return Integer.compare(e1.getAge(), e2.getAge());}});for (Employee e : list) {System.out.println(e);}}public static void main(String[] args) {test();}
}
# 程序输出
com.lambda.Employee@404b9385
com.lambda.Employee@6d311334
com.lambda.Employee@682a0b20
com.lambda.Employee@3d075dc0

相关文章:

原来Lambda表达式是这样写的

原来Lambda表达式是这样写的 lambda 是一个匿名函数&#xff0c;我们可以把 lambda 表达式理解为是一段可以传递的代码。 lambda 简明地将代码或方法作为参数传递进去执行。 函数式编程&#xff1a;核心是把函数作为值。 函数式接口 &#xff1a;只有一个抽象方法的接口称之…...

smartsofthelp 5.0 最专业的数据库优化工具,数据库配置优化,数据库高并发优化,SQL 语句优化...

下载地址:百度网盘 请输入提取码 SQL操作返回历史记录&#xff1a; 2023-08-21 20:42:08:220 输入&#xff1a;select version as 版本号 2023-08-21 20:42:08:223 输出&#xff1a;当前数据库实例版本号&#xff1a;Microsoft SQL Server 2012 - 11.0.2100.60 (X64) …...

智影 R100:首款三维Mesh建模的SLAM激光扫描仪

近年来&#xff0c;激光SLAM系统凭借其更加快速且准确获取更丰富信息的优势&#xff0c;迅速风靡测绘领域&#xff0c;让原本耗时耗力的外业测量变得更加高效。手持激光扫描仪作为基于激光SLAM技术衍生的众多产品之一&#xff0c;相较于架站式激光扫描仪更加轻巧便利&#xff0…...

Next.js - Loading UI and Streaming

特殊文件 loading.js 可帮助您使用 React Suspense 创建有意义的加载用户界面。使用此约定&#xff0c;您可以在加载路由段内容时显示来自服务器的即时加载状态。渲染完成后&#xff0c;新的内容会自动切换进来。 即时加载状态 即时加载状态是在导航时立即显示的后备用户界面…...

快速解决Ubuntu 中 wine 程序 中文显示为方块/显示错误/无法显示中文(2023)

解决办法就是在创建prefix的命令行里加上LANG“zh_CN.UTF8” 或 LC_ALL“zh_CN.UTF8”&#xff0c;并安装cjkfonts&#xff0c;即可。 1、生成prefix、安装cjk字体 以下是基本流程&#xff1a; 现在假定wine和winetricks已经装好&#xff0c; // 先创建一个prefix&#xff0…...

漏洞指北-VulFocus靶场专栏-中级02

漏洞指北-VulFocus靶场专栏-中级02 中级005 &#x1f338;thinkphp lang 命令执行&#xff08;thinkphp:6.0.12&#xff09;&#x1f338;step1&#xff1a;burp suite 抓包 修改请求头step2 修改成功&#xff0c;访问shell.php 中级006 &#x1f338;Metabase geojson任意文件…...

【开源三方库】bignumber.js:一个大数数学库

OpenHarmony&#xff08;OpenAtom OpenHarmony简称“OpenHarmony”&#xff09;三方库&#xff0c;是经过验证可在OpenHarmony系统上可重复使用的软件组件&#xff0c;可帮助开发者快速开发OpenHarmony应用。如果是发布到开源社区&#xff0c;称为开源三方库&#xff0c;开发者…...

【C++】iota函数 + sort函数实现基于一个数组的多数组对应下标绑定排序

目录 一、iota函数 1. 函数解析 ​① 迭代器类型(补充) ② 头文件 ③ 参数 2. 函数用途与实例 二、sort函数 1、 函数解读 2、实现倒序排列 2.1 greater 与 less 模板参数 2.2 lambda表达式 三、下标绑定排序&#xff08;zip&#xff09; --- 833.字符串中的查找与替换 一、…...

C# window forms 进度条实现

在 C# Windows Forms 应用程序中&#xff0c;如果在后台执行长时间运行的任务&#xff0c;并希望同时更新进度条&#xff0c;可以使用多线程来实现。这将确保进度条的更新不会阻塞主线程&#xff0c;从而保持界面的响应性。以下是一个示例&#xff0c;演示了如何在后台执行任务…...

ListNode相关

目录 2. 链表相关题目 2.1 合并两个有序链表&#xff08;简单&#xff09;&#xff1a;递归 2.2 删除排序链表中的重复元素&#xff08;简单&#xff09;&#xff1a;一次遍历 2.3 两链表相加&#xff08;中等&#xff09;&#xff1a;递归 2.4 删除链表倒数第N个节点&…...

docker的资源控制及docker数据管理

目录 一.docker的资源控制 1.CPU 资源控制 1.1 资源控制工具 1.2 cgroups有四大功能 1.3 设置CPU使用率上限 1.4 进行CPU压力测试 1.5 设置50%的比例分配CPU使用时间上限 1.6 设置CPU资源占用比&#xff08;设置多个容器时才有效&#xff09; 1.6.1 两个容器测试cpu 2&…...

通过请求头传数据向后端发请求

axios &#xff08;get post请求、头部参数添加&#xff09;傻瓜式入门axios_axiospost请求参数_web_blog的博客-CSDN博客...

产品流程图是什么?怎么做?

产品流程图是什么&#xff1f; 产品流程图是一种图形化的表达方式&#xff0c;用于描述产品开发、制造、销售、使用等各个阶段中涉及的流程、步骤和关系。它通过图形符号、箭头、文本等元素&#xff0c;展示了产品的各个环节之间的关联和顺序&#xff0c;通常被用于可视化产…...

面试之快速学习STL-map

关联式容器 包括 map、multimap、set 以及 multiset 这 4 种容器。和序列式容器区别&#xff1a; a . 关联式容器在存储元素时还会为每个元素在配备一个键&#xff0c;整体以键值对的方式存储到容器中。 b . 相比前者&#xff0c;关联式容器可以通过键值直接找到对应的元素&am…...

ES的索引结构与算法解析

提到ES&#xff0c;大多数爱好者想到的都是搜索引擎&#xff0c;但是明确一点&#xff0c;ES不等同于搜索引擎。不管是谷歌、百度、必应、搜狗为代表的自然语言处理(NLP)、爬虫、网页处理、大数据处理的全文搜索引擎&#xff0c;还是有明确搜索目的的搜索行为&#xff0c;如各大…...

32.Netty源码之服务端如何处理客户端新建连接

highlight: arduino-light 服务端如何处理客户端新建连接 Netty 服务端完全启动后&#xff0c;就可以对外工作了。接下来 Netty 服务端是如何处理客户端新建连接的呢&#xff1f; 主要分为四步&#xff1a; md Boss NioEventLoop 线程轮询客户端新连接 OP_ACCEPT 事件&#xff…...

代码随想录day11

20. 有效的括号 ● 力扣题目链接 ● 给定一个只包括 ‘(’&#xff0c;‘)’&#xff0c;‘{’&#xff0c;‘}’&#xff0c;‘[’&#xff0c;‘]’ 的字符串&#xff0c;判断字符串是否有效。 ● 有效字符串需满足&#xff1a; ● 左括号必须用相同类型的右括号闭合。 ● 左…...

RabbitMQ实习面试题

RabbitMQ实习面试题 在 RabbitMQ 中&#xff0c;确保生产者消息正确发布以及确保消费者已经消费是非常重要的任务。以下是一些方法和策略&#xff0c;可以帮助您在 RabbitMQ 中实现这些目标&#xff1a; 确保生产者消息正确发布&#xff1a; 持久化消息&#xff1a;将消息设…...

Electron入门,项目运行,只需四步轻松搞定。

electron 简单介绍&#xff1a; 实现&#xff1a;HTML/CSS/JS桌面程序&#xff0c;搭建跨平台桌面应用。 electron 官方文档&#xff1a; [https://electronjs.org/docs] 本文是基于以下2篇文章且自行实践过的&#xff0c;可行性真实有效。 文章1&#xff1a; https://www.cnbl…...

【C++】visualstudio环境安装

记录了部分安装步骤&#xff0c;可能有点不全&#xff0c;参考下&#xff0c;需要的磁盘空间差不多20GB&#xff1b; 下载 https://visualstudio.microsoft.com/zh-hans/vs/ 下载完成&#xff1a; 双击进入安装状态&#xff1a; 根据自己的需求勾选安装项&#xff1a; 选择…...

使用MySQL:5.6和owncloud镜像搭建个人网盘

拉取镜像 [rootkvm ~]# docker pull mysql:5.6[rootkvm ~]# docker pull owncloud启动mysql容器 [rootkvm ~]# docker run -d --name db1 -e MYSQL_ROOT_PASSWORDroot mysql:5.6 db832e4e4333a0e9a7c152a67272721fdbe5381054090c5eb24f90455390a852 [rootkvm ~]# docker ps …...

php中创建对象时传递的参数是构造方法

PHP中创建对象时&#xff0c;可以通过构造方法的参数来传递参数值。构造方法是一个特殊的方法&#xff0c;在创建对象时会自动调用&#xff0c;用于进行对象的初始化操作。 以下是一个示例代码&#xff0c;展示了如何在PHP中使用构造方法传递参数&#xff1a; class MyClass …...

C++并发及互斥保护示例

最近要写一个多线程的并发数据库&#xff0c;主要是希望使用读写锁实现库的并发访问&#xff0c;同时考虑到其他平台(如Iar)没有C的读写锁&#xff0c;需要操作系统提供&#xff0c;就将读写锁封装起来。整个过程还是比较曲折的&#xff0c;碰到了不少问题&#xff0c;在此就简…...

新手常犯的错误,anzo capital昂首资本一招避免少走弯路

新手是不是经常交易中赚不到钱&#xff0c;今天anzo capital昂首资本就盘点一下新手常犯的错误&#xff0c;一招教你少走弯路。 一.随便选择交易账户 开立实时账户时选择正确的账户类型&#xff0c;anzo capital昂首资本教你比较所有提供的账户类型&#xff0c;选择最符合财务…...

Java Vue (el-date-picker组件) 前后端 关于时间格式数据的处理方法

前端使用 elment-ui 组件 el-date-picker 其中组件需要格式化时间&#xff0c;增加属性 value-format"yyyy-MM-dd" 后端 Java 接收参数类型 后端Dto 使用Date接收&#xff0c;并添加JsonFormat注解 JsonFormat(pattern"yyyy-MM-dd") private Date testTi…...

Python爬虫——scrapy_多条管道下载

定义管道类&#xff08;在pipelines.py里定义&#xff09; import urllib.requestclass DangDangDownloadPipelines:def process_item(self, item, spider):url http: item.get(src)filename ../books_img/ item.get(name) .jpgurllib.request.urlretrieve(url, filename…...

lombok启动不生效(什么方法都试了,可还是不生效怎么办 ?! 救救我)

使用IntelliJ IDEA 2021.1.3&#xff08;Ultimate Edition&#xff09;时提示Lombok不生效 java: You aren’t using a compiler supported by lombok, so lombok will not work and has been disabled. 方式一&#xff1a;我们手动更新一下版本到以下版本 <!--Lombok--&…...

element文本域禁止手动拉伸、两种方式、textarea

文章目录 style方式element自带的禁止拉伸方法建议 style方式 html <el-inputv-model"content":rows"3"class"r_n"type"textarea"maxlength"40"placeholder""style"height: 100%;" />css style…...

c#中lambda表达式缩写推演

Del<string> ml new Del<string>(Notify);//泛型委托的实例化&#xff0c;并关联Nofity方法 Del<string> ml new Del<string>(delegate (string str) { return str.Length; });//将Nofity变更为匿名函数 Del<string> ml delegate(string str)…...

无涯教程-PHP - 循环语句

PHP中的循环用于执行相同的代码块指定的次数。 PHP支持以下四种循环类型。 for - 在代码块中循环指定的次数。 while - 如果且只要指定条件为真&#xff0c;就会循环遍历代码块。 do ... while - 循环执行一次代码块&#xf…...

网站链接dw怎么做/广告传媒公司经营范围

白驹微过隙&#xff0c;指上细流沙。时间飞逝啊&#xff01;转眼之间&#xff0c;四五个月过去了&#xff0c;伴随着中国迈进2020的新时代的元旦的步伐声&#xff0c;我的考研生活暂时告了一个小段落。距今的这些天&#xff0c;忙完了各种小事情&#xff0c;也是时候整理整理之…...

网站的登记表是怎么做的/百度一下电脑版首页网址

postman的使用方法详解&#xff01;最全面的教程 文章来源&#xff1a;http://www.cnplugins.com/tool/specify-postman-methods.html一 简介 Postman 是一款功能超级强大的用于发送 HTTP 请求的 Chrome插件 。做web页面开发和测试的人员应该是无人不晓无人不用&#xff01;其主…...

网站建设费属于广告费/seo推广外包企业

本期头条 全球发布&#xff01;阿里云Serverless Kubernetes全球免费公测 近两年&#xff0c;Kubernetes&#xff08;以下简称K8S&#xff09;以及Serverless两大技术备受云计算厂商追捧&#xff0c;二者结合的新服务模式已经成为行业发展的新趋势&#xff0c;主流公有云厂商相…...

网站图片加载优化/优化官网咨询

二十年前读中学的时候&#xff0c;有一位语文老师特别促狭。有一次上作文课&#xff0c;上来说&#xff0c;“今天我要请一位同学来读一读他自己的作文。不过这次和以前不同&#xff0c;我要求连标点符号也要读出来。小K同学&#xff0c;上讲台来读吧&#xff01;”小K是班里一…...

大渡口的网站开发公司电话/如何广告推广

好文章&#xff0c;要转载&#xff01; 前面讲了paint&#xff0c;后面会花几篇主要讲讲canvas&#xff0c;并且由于最近项目比较紧&#xff0c;所以近期的文章都会“短小精悍”&#xff1b; paint 作为画笔&#xff0c;里面有非常多而强大的设置方法&#xff0c;比如设置颜…...

四川旅游攻略自由行攻略/优化大师下载

一&#xff1a;ClassLoader类加载器&#xff0c;主要的作用是将class文件加载到jvm虚拟机中。jvm启动的时候&#xff0c;并不是一次性加载所有的类&#xff0c;而是根据需要动态去加载类&#xff0c;主要分为隐式加载和显示加载。 隐式加载&#xff1a;程序代码中不通过调用Cla…...