【JAVA重要知识 | 第五篇】暴打Java8新特性—(Lambda、方法引用、Stream流、函数式接口、Date Time API、Optional类)
文章目录
- 5.Java8新特性
- 5.1新特性列表
- 5.2Lambda 表达式
- 5.2.1函数式思想
- 5.2.2举例
- (1)方式一:创建对象
- (2)方式二:匿名内部类
- (3)方式三:Lambda
- 5.2.3Lambda表达式的标准格式
- 5.2.4练习
- (1)练习1——抽象方法无参无返回值
- ①通过实现类方法
- ②匿名内部类
- ③lambda
- (2)练习2——抽象方法带参无返回值
- ①匿名内部类
- ②lambda
- (3)练习3——抽象方法带参带返回值
- 5.2.5Lambda的省略模式
- (1)举例
- 5.2.6lambad表达式与匿名内部类的区别
- 5.3方法引用
- 5.3.1介绍
- 5.3.2方法引用的类型
- (1)调用类的静态方法
- ①语法
- ②举例
- (2)调用传入的实例参数的方法
- ①语法
- ②举例
- (3)调用已经存在的实例的方法
- ①语法
- ②举例
- (4)调用类的构造函数
- ①语法
- ②举例
- 5.3.3练习
- (1)练习一
- (2)练习二
- 5.4Stream流
- 5.4.1定义
- 5.4.2流的操作类型
- (1)中间操作
- (2)终端操作
- 5.4.3举例
- (1)创建流
- (2)操作流
- ①过滤
- ②映射
- ③匹配
- ④组合
- (3)转换流
- 5.4.4Stream 与Collection 的区别
- 5.5函数式接口
- 5.5.1定义
- 5.5.2举例
5.Java8新特性
5.1新特性列表
- Lambda 表达式:Lambda 允许把函数作为一个方法的参数(函数作为参数传递到方法中)。
- 方法引用:方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少默认方法: 默认方法就是一个在接口里面有了一个实现的方法。
- Stream API:新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。
- Date Time API: 加强对日期与时间的处理。
- 新工具:新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器jdeps。
- Optional 类: Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。
- Nashorn, JavaScript 引擎: Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用。
5.2Lambda 表达式
5.2.1函数式思想
- 在数学中,函数就是有输入量、输出量的一套计算方案,也就是“拿数据做操作”
- 面向对象思想 强调“必须通过对象的形式来做事情”
- 函数式思想 则尽量忽略面向对象的复杂语法:“强调做什么,而不是以什么形式去做”
而我们要学习的Lambda表达式就是函数式思想的体现
5.2.2举例
- 需求:启动一个线程,在控制台输出一句话:多线程程序启动了
(1)方式一:创建对象
定义一个类MyRunnable实现Runnable接口,并重写run()方法
//创建MyRunnable类的对象
class MyRunnable implements Runnable{@Overridepublic void run() {System.out.println("多线程程序启动了...");}
}public class LambdaDemo {public static void main(String[] args) {//实现类的方式实现需求MyRunnable my = new MyRunnable();//创建Thread类的对象,把MyRunnable的对象作为构造参数传递Thread t = new Thread(my);//启动线程t.start();}
}
(2)方式二:匿名内部类
- 匿名内部类中重写run()方法的代码分析
- 方法形式参数为空,说明调用方法时不需要传递参数
- 方法返回值类型为void,说明方法执行没有结果返回
- 方法体中的内容,是我们具体要做的事情
public class LambdaDemo {public static void main(String[] args) {//匿名内部类的方式改进new Thread(new Runnable() {@Overridepublic void run() {System.out.println("多线程程序启动了...");}}).start();}
}
(3)方式三:Lambda
public class LambdaDemo {public static void main(String[] args) {//Lambda表达式改进new Thread(() -> {System.out.println("多线程程序启动了...");}).start();}
}
5.2.3Lambda表达式的标准格式
- 组成Lambda表达式的三要素:形式参数,箭头,代码块
- Lambda表达式的格式
- 格式:(形式参数) -> {代码块}
- 形式参数:如果有多个参数,参数之间用逗号隔开;如果没有参数,留空即可
- ->:由英文中画线和大于符号组成,固定写法。代表指向动作
- 代码块:是我们具体要做的事情,也就是以前我们写的方法体内容
- Lambda表达式的 使用前提
- 有一个接口
- 接口中有且仅有一个抽象方法
5.2.4练习
(1)练习1——抽象方法无参无返回值
- 定义一个接口(Eatable),里面定义一个抽象方法:void eat();
public interface Eatable {void eat();
}
- 定义一个测试类(EatableDemo),在测试类中提供两个方法
- 一个方法是:useEatable(Eatable e)
- 一个方法是主方法,在主方法中调用useEatable方法
①通过实现类方法
- 实现类实现Eatable,并重写eat方法
class EatableImpl implements Eatable{@Overridepublic void eat() {System.out.println("一天一苹果,医生远离我");}
}
public class EatableDemo {public static void main(String[] args) {//在主方法中调用useEatable方法Eatable e = new EatableImpl();useEatable(e);}private static void useEatable(Eatable e){e.eat();}
}
②匿名内部类
public class EatableDemo {public static void main(String[] args) {//匿名内部类useEatable(new Eatable() {@Overridepublic void eat() {System.out.println("一天一苹果,医生远离我");}});}private static void useEatable(Eatable e){e.eat();}
}
③lambda
Eatable e是一个接口,并只含有一个抽象方法,无参无返回值方法:void eat()
以下lambda实现方式相当于实现该接口,并实现该方法
public class EatableDemo {public static void main(String[] args) {//用Lambda表达式useEatable(() -> {System.out.println("一天一苹果,医生远离我");});}private static void useEatable(Eatable e){e.eat();}
}
(2)练习2——抽象方法带参无返回值
- 定义一个接口(Flyable),里面定义一个抽象方法,void fly(String s);
public interface Flyable{void fly(String s);
}
- 定义一个测试类(FlyableDemo),在测试类中提供两个方法
- 一个方法是:useFlyable(Flyable f)
- 一个方法是主方法,在主方法中调用useFlyable方法
①匿名内部类
public class FlyableDemo {public static void main(String[] args) {//在主方法中调用useFlyable方法//匿名内部类useFlyable(new Flyable() {@Overridepublic void fly(String s) {System.out.println(s);System.out.println("飞机自驾游");}});}private static void useFlyable(Flyable f){f.fly("风和日丽,晴空万里");}
}
②lambda
public class FlyableDemo {public static void main(String[] args) {//LambdauseFlyable((String s)-> {System.out.println(s);System.out.println("飞机自驾游");});}private static void useFlyable(Flyable f){f.fly("风和日丽,晴空万里");}
}
(3)练习3——抽象方法带参带返回值
这里就不过多赘述了,和练习2差不多,在最后添加返回值语句即可
5.2.5Lambda的省略模式
- 省略规则
- 参数类型可以省略。但是有多个参数的情况下,不能只省略一个
- 如果参数有且仅有一个,那么小括号可以省略
- 如果代码块的语句只有一条,可以省略大括号和分号,甚至是return
(1)举例
- 定义一个接口(Flyable),里面定义一个抽象方法:void fly(String s);
public interface Flyable{void fly(String s);
}
- 定义一个接口(Addable),里面定义一个抽象方法:int add(int x,int y);
public interface Addable {int add(int x,int y);
}
/*Lambda表达式的省略模式*/
public class LambdaDemo {public static void main(String[] args) {//useAddable((int x,int y) -> {// return x+y;//});//1.参数的类型可以省略,但是有多个参数的情况下,不能只省略一个useAddable((x,y) -> {return x+y;});//useFlyable((String s) ->{// System.out.println(s);//});//2.如果参数有且只有一个,那么小括号可以省略useFlyable( s->{System.out.println(s);});//3.如果代码块的语句只有一条,可以省略大括号和分号useFlyable(s -> System.out.println(s));//4.如果代码块的语句只有一条,可以省略大括号和分号;如果有return,return也要省略useAddable((x,y) -> x+y );}private static void useFlyable(Flyable f){f.fly("风和日丽,晴空万里");}private static void useAddable(Addable a){int sum = a.add(10,20);System.out.println(sum);}
}
5.2.6lambad表达式与匿名内部类的区别
匿名内部类 | lambda | |
---|---|---|
创建的对象类型 | 接口、抽象类、具体类 | 接口 |
使用限制 | 接口可有一个或多个抽象方法 | 接口有且只有一个抽象方法 |
实现原理 | 编译之后,产生一个单独的.class字节码文件 | 编译之后,没有一个单独的.class字节码文件。对应的字节码会在运行的时候动态生成 |
5.3方法引用
5.3.1介绍
- 定义:方法引用是指通过方法的名字来指向一个方法
- 优点:方法引用可以使语言的构造更紧凑简洁,减少冗余代码
- 与lambda的比较:方法引用(MethodReference)是Lambda表达式的另一种格式,在某些场景下可以提高代码的可读性
5.3.2方法引用的类型
方法引用可以分为分四类:调用类的静态方法、调用传入的实例参数的方法、调用已经存在的实例的方法、调用类的构造函数
以下将从四种类型的方法引用出发,探讨lambda与方法引用的区分点
(1)调用类的静态方法
①语法
//lambda
(args) -> Class.staticMethod(args)//方法引用
Class::static_method
符合上面形式的调用,不管有多少参数,都省略掉,编译器自动会帮我们传入
②举例
// Lambda 表达式
Function<Integer, String> intToStringLambda = (num) -> String.valueOf(num);// 方法引用
Function<Integer, String> intToString = String::valueOf;
Function<Integer, String>
表示一个函数式接口(Functional Interface),它接受一个 Integer 类型的参数,并返回一个 String 类型的结果。具体来说,
Function<Integer, String>
是 Java 中的函数式接口,它包含一个抽象方法apply
,用于将输入的 Integer 类型参数转换为输出的 String 类型结果。在这种情况下,intToString
就是一个函数,可以将 Integer 类型的值转换为 String 类型的值。
(2)调用传入的实例参数的方法
①语法
//lambda
(obj, args) -> obj.instanceMethod(args)//方法引用
ObjectType::instanceMethod
②举例
String str = "Hello World";
// Lambda 表达式
BiFunction<String, Integer, String> substringLambda = (str, index) -> str.substring(index);// 方法引用
BiFunction<String, Integer, String> substring = String::substring;
实现
BiFunction
接口的apply
方法,直接引用了String
类的substring
方法。
(3)调用已经存在的实例的方法
①语法
//lambda
(args) -> obj.instanceMethod(args)//方法引用
obj::instanceMethod
②举例
// Lambda 表达式
String str = "Hello World";
Supplier<Integer> strLengthLambda = () -> str.length();// 方法引用
String str = "Hello World";
Supplier<Integer> strLength = str::length;
Supplier
是 Java 中的一个函数式接口,它不接受任何参数,但返回一个结果。
(4)调用类的构造函数
①语法
//lambda
(args) -> new ClassName(args)//方法引用
ClassName::new
②举例
// Lambda 表达式
Supplier<List<String>> listSupplierLambda = () -> new ArrayList<>();// 方法引用
Supplier<List<String>> listSupplier = ArrayList::new;
Supplier
是 Java 中的一个函数式接口,它不接受任何参数,但返回一个结果。
5.3.3练习
(1)练习一
import java.util.List;
import java.util.ArrayList;public class Java8Tester {public static void main(String args[]){List<String> names = new ArrayList();names.add("Google");names.add("Runoob");names.add("Taobao");names.add("Baidu");names.add("Sina");names.forEach(System.out::println);}
}
实例中我们将 System.out::println 方法作为静态方法来引用。
属于调用类的静态方法一类
结果:
Google
Runoob
Taobao
Baidu
Sina
(2)练习二
Consumer<String> consumer1 = new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}
};//lambda表达式
Consumer<String> consumer2 = ;//方法引用
Consumer<String> consumer3 = ;
答案:
//lambda
Consumer<String> consumer2 = (s)->{System.out.println(s);
}
//方法引用
Consumer<String> consumer3 = System.out::println;
属于调用类的静态方法一类
5.4Stream流
5.4.1定义
Stream 就好像一个高级的迭代器,但只能遍历一次,就好像一江春水向东流;在流的过程中,对流中的元素执行一些操作,比如“过滤掉长度大于 10 的字符串”、“获取每个字符串的首字母”等。
5.4.2流的操作类型
要想操作流,首先需要有一个数据源,可以是数组或者集合。每次操作都会返回一个新的流对象,方便进行链式操作,但原有的流对象会保持不变。
流的操作可以分为两种类型:
1)中间操作,可以有多个,每次返回一个新的流,可进行链式操作。
2)终端操作,只能有一个,每次执行完,这个流也就用光光了,无法执行下一个操作,因此只能放在最后。
来举个例子。
List<String> list = new ArrayList<>();
list.add("武汉加油");
list.add("中国加油");
list.add("世界加油");
list.add("世界加油");long count = list.stream().distinct().count();
System.out.println(count);
(1)中间操作
distinct()
方法是一个中间操作(去重),它会返回一个新的流(没有共同元素)。
(2)终端操作
count()
方法是一个终端操作,返回流中的元素个数
long count();
中间操作不会立即执行,只有等到终端操作的时候,流才开始真正地遍历,用于映射、过滤等。通俗点说,就是一次遍历执行多个操作,性能就大大提高了。
5.4.3举例
(1)创建流
- 如果是数组的话,可以使用
Arrays.stream()
或者Stream.of()
创建流; - 如果是集合的话,可以直接使用
stream()
方法创建流,因为该方法已经添加到 Collection 接口中。
public class CreateStreamDemo {public static void main(String[] args) {String[] arr = new String[]{"武汉加油", "中国加油", "世界加油"};Stream<String> stream = Arrays.stream(arr);stream = Stream.of("武汉加油", "中国加油", "世界加油");List<String> list = new ArrayList<>();list.add("武汉加油");list.add("中国加油");list.add("世界加油");stream = list.stream();}
}
查看 Stream 源码的话,你会发现 of()
方法内部其实调用了 Arrays.stream()
方法。
public static<T> Stream<T> of(T... values) {return Arrays.stream(values);
}
另外,集合还可以调用 parallelStream()
方法创建并发流,默认使用的是 ForkJoinPool.commonPool()
线程池。
List<Long> aList = new ArrayList<>();
Stream<Long> parallelStream = aList.parallelStream();
(2)操作流
Stream 类提供了很多有用的操作流的方法
①过滤
通过
filter()
方法可以从流中筛选出我们想要的元素。
public class FilterStreamDemo {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("周杰伦");list.add("王力宏");list.add("陶喆");list.add("林俊杰");Stream<String> stream = list.stream().filter(element -> element.contains("王"));stream.forEach(System.out::println);}
}
-
filter()
方法接收的是一个 Predicate(Java 8 新增的一个函数式接口,接受一个输入参数返回一个布尔值结果)类型的参数,因此,我们可以直接将一个 Lambda 表达式传递给该方法,比如说element -> element.contains("王")
就是筛选出带有“王”的字符串。 -
forEach()
方法接收的是一个 Consumer(Java 8 新增的一个函数式接口,接受一个输入参数并且无返回的操作)类型的参数,类名 :: 方法名
是 Java 8 引入的新语法(方法引用),System.out
返回 PrintStream 类,println 方法你应该知道是打印的。(该类型为调用类的静态方法) -
输出结果:
王力宏
②映射
如果想通过某种操作把一个流中的元素转化成新的流中的元素,可以使用 map()
方法。
public class MapStreamDemo {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("周杰伦");list.add("王力宏");list.add("陶喆");list.add("林俊杰");Stream<Integer> stream = list.stream().map(String::length);stream.forEach(System.out::println);}
}
map()
方法接收的是一个 Function(Java 8 新增的一个函数式接口,接受一个输入参数 T,返回一个结果 R)类型的参数,此时参数 为 String 类的 length 方法(该类型为调用传入的实例参数的方法),也就是把 Stream<String>
的流转成一个 Stream<Integer>
的流。
- 输出结果:
3
3
2
3
③匹配
Stream 类提供了三个方法可供进行元素匹配,它们分别是:
anyMatch()
,只要有一个元素匹配传入的条件,就返回 true。allMatch()
,只有有一个元素不匹配传入的条件,就返回 false;如果全部匹配,则返回 true。noneMatch()
,只要有一个元素匹配传入的条件,就返回 false;如果全部不匹配,则返回 true。
public class MatchStreamDemo {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("周杰伦");list.add("王力宏");list.add("陶喆");list.add("林俊杰");boolean anyMatchFlag = list.stream().anyMatch(element -> element.contains("王"));boolean allMatchFlag = list.stream().allMatch(element -> element.length() > 1);boolean noneMatchFlag = list.stream().noneMatch(element -> element.endsWith("沉"));System.out.println(anyMatchFlag);System.out.println(allMatchFlag);System.out.println(noneMatchFlag);}
}
因为“王力宏”以“王”字开头,所以 anyMatchFlag 应该为 true;因为“周杰伦”、“王力宏”、“陶喆”、“林俊杰”的字符串长度都大于 1,所以 allMatchFlag 为 true;因为 4 个字符串结尾都不是“沉”,所以 noneMatchFlag 为 true。
- 输出结果
true
true
true
④组合
reduce()
方法的主要作用是把 Stream 中的元素组合起来,它有两种用法:
-
Optional<T> reduce(BinaryOperator<T> accumulator)
没有起始值,只有一个参数,就是运算规则,此时返回 Optional。
-
T reduce(T identity, BinaryOperator<T> accumulator)
有起始值,有运算规则,两个参数,此时返回的类型和起始值类型一致。
来看下面这个例子。
public class ReduceStreamDemo {public static void main(String[] args) {Integer[] ints = {0, 1, 2, 3};List<Integer> list = Arrays.asList(ints);Optional<Integer> optional = list.stream().reduce((a, b) -> a + b); //lambda写法Optional<Integer> optional1 = list.stream().reduce(Integer::sum); //方法引用写法System.out.println(optional.orElse(0)); //6System.out.println(optional1.orElse(0)); //6int reduce = list.stream().reduce(6, (a, b) -> a + b); //有起始值6System.out.println(reduce); int reduce1 = list.stream().reduce(6, Integer::sum); //有起始值6System.out.println(reduce1);}
}
运算规则可以是 Lambda 表达式(比如 (a, b) -> a + b
),也可以是类名::方法名(比如 Integer::sum
)。
程序运行的结果如下所示:
0、1、2、3 在没有起始值相加的时候结果为 6;有起始值 6 的时候结果为 12。
6
6
12
12
(3)转换流
既然可以把集合或者数组转成流,那么也应该有对应的方法,将流转换回去——collect()
方法就满足了这种需求。
public class CollectStreamDemo {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("周杰伦");list.add("王力宏");list.add("陶喆");list.add("林俊杰");String[] strArray = list.stream().toArray(String[]::new);System.out.println(Arrays.toString(strArray)); //[周杰伦, 王力宏, 陶喆, 林俊杰]List<Integer> list1 = list.stream().map(String::length).collect(Collectors.toList());List<String> list2 = list.stream().collect(Collectors.toCollection(ArrayList::new));System.out.println(list1); //[3, 3, 2, 3]System.out.println(list2); //[周杰伦, 王力宏, 陶喆, 林俊杰]String str = list.stream().collect(Collectors.joining(", ")).toString();System.out.println(str); //周杰伦, 王力宏, 陶喆, 林俊杰}
}
toArray()
方法可以将流转换成数组,你可能比较好奇的是 String[]::new,它是什么东东呢?来看一下 toArray()
方法的源码。
<A> A[] toArray(IntFunction<A[]> generator);
也就是说 String[]::new
是一个 IntFunction,一个可以产生所需的新数组的函数,可以通过反编译字节码看看它到底是什么:
String[] strArray = (String[])list.stream().toArray((x$0) -> {return new String[x$0];
});
System.out.println(Arrays.toString(strArray));
也就是==相当于返回了一个指定长度的字符串数组==。
当我们需要把一个集合按照某种规则转成另外一个集合的时候,就可以配套使用 map()
方法和 collect()
方法。
List<Integer> list1 = list.stream().map(String::length).collect(Collectors.toList());
通过 stream()
方法创建集合的流后,再通过 map(String:length)
将其映射为字符串长度的一个新流,最后通过 collect()
方法将其转换成新的集合。
Collectors 是一个收集器的工具类,内置了一系列收集器实现,比如说 toList()
方法将元素收集到一个新的 java.util.List
中;比如说 toCollection()
方法将元素收集到一个新的 java.util.ArrayList
中;比如说 joining()
方法将元素收集到一个可以用分隔符指定的字符串中。
- 输出结果
[周杰伦, 王力宏, 陶喆, 林俊杰]
[3, 3, 2, 3]
[周杰伦, 王力宏, 陶喆, 林俊杰]
周杰伦, 王力宏, 陶喆, 林俊杰
5.4.4Stream 与Collection 的区别
5.5函数式接口
5.5.1定义
- 函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
- 函数式接口可以被隐式转换为 lambda 表达式。
- Lambda 表达式和方法引用(实际上也可认为是Lambda表达式)上。
如定义了一个函数式接口如下:
@FunctionalInterface
interface GreetingService
{void sayMessage(String message);
}
那么就可以使用Lambda表达式来表示该接口的一个实现(注:JAVA 8 之前一般是用匿名类实现的):
GreetingService greetService1 = message -> System.out.println("Hello " + message);
函数式接口可以对现有的函数友好地支持 lambda。
JDK 1.8 之前已有的函数式接口:
- java.lang.Runnable
- java.util.concurrent.Callable
- java.security.PrivilegedAction
- java.util.Comparator
- java.io.FileFilter
- java.nio.file.PathMatcher
- java.lang.reflect.InvocationHandler
- java.beans.PropertyChangeListener
- java.awt.event.ActionListener
- javax.swing.event.ChangeListener
JDK1.8新增加的函数接口:
- java.util.function
java.util.function 它包含了很多类,用来支持 Java的函数式编程,该包中的函数式接口有:
1 | BiConsumer<T,U> 代表了一个接受两个输入参数的操作,并且不返回任何结果 |
---|---|
2 | BiFunction<T,U,R> 代表了一个接受两个输入参数的方法,并且返回一个结果 |
3 | BinaryOperator 代表了一个作用于于两个同类型操作符的操作,并且返回了操作符同类型的结果 |
4 | BiPredicate<T,U> 代表了一个两个参数的boolean值方法 |
5 | BooleanSupplier代表了boolean值结果的提供方 |
6 | Consumer 代表了接受一个输入参数并且无返回的操作 |
7 | DoubleBinaryOperator代表了作用于两个double值操作符的操作,并且返回了一个double值的结果。 |
8 | DoubleConsumer代表一个接受double值参数的操作,并且不返回结果。 |
9 | DoubleFunction 代表接受一个double值参数的方法,并且返回结果 |
10 | DoublePredicate代表一个拥有double值参数的boolean值方法 |
11 | DoubleSupplier代表一个double值结构的提供方 |
12 | DoubleToIntFunction接受一个double类型输入,返回一个int类型结果。 |
13 | DoubleToLongFunction接受一个double类型输入,返回一个long类型结果 |
14 | DoubleUnaryOperator接受一个参数同为类型double,返回值类型也为double 。 |
15 | **Function<T,R>**接受一个输入参数,返回一个结果。 |
16 | IntBinaryOperator接受两个参数同为类型int,返回值类型也为int 。 |
17 | IntConsumer接受一个int类型的输入参数,无返回值 。 |
18 | IntFunction 接受一个int类型输入参数,返回一个结果 。 |
19 | IntPredicate:接受一个int输入参数,返回一个布尔值的结果。 |
20 | IntSupplier无参数,返回一个int类型结果。 |
21 | IntToDoubleFunction接受一个int类型输入,返回一个double类型结果 。 |
22 | IntToLongFunction接受一个int类型输入,返回一个long类型结果。 |
23 | IntUnaryOperator接受一个参数同为类型int,返回值类型也为int 。 |
24 | LongBinaryOperator接受两个参数同为类型long,返回值类型也为long。 |
25 | LongConsumer接受一个long类型的输入参数,无返回值。 |
26 | LongFunction 接受一个long类型输入参数,返回一个结果。 |
27 | LongPredicateR接受一个long输入参数,返回一个布尔值类型结果。 |
28 | LongSupplier无参数,返回一个结果long类型的值。 |
29 | LongToDoubleFunction接受一个long类型输入,返回一个double类型结果。 |
30 | LongToIntFunction接受一个long类型输入,返回一个int类型结果。 |
31 | LongUnaryOperator接受一个参数同为类型long,返回值类型也为long。 |
32 | ObjDoubleConsumer 接受一个object类型和一个double类型的输入参数,无返回值。 |
33 | ObjIntConsumer 接受一个object类型和一个int类型的输入参数,无返回值。 |
34 | ObjLongConsumer 接受一个object类型和一个long类型的输入参数,无返回值。 |
35 | Predicate 接受一个输入参数,返回一个布尔值结果。 |
36 | Supplier 无参数,返回一个结果。 |
37 | ToDoubleBiFunction<T,U> 接受两个输入参数,返回一个double类型结果 |
38 | ToDoubleFunction 接受一个输入参数,返回一个double类型结果 |
39 | ToIntBiFunction<T,U> 接受两个输入参数,返回一个int类型结果。 |
40 | ToIntFunction 接受一个输入参数,返回一个int类型结果。 |
41 | ToLongBiFunction<T,U> 接受两个输入参数,返回一个long类型结果。 |
42 | ToLongFunction 接受一个输入参数,返回一个long类型结果。 |
43 | UnaryOperator 接受一个参数为类型T,返回值类型也为T。 |
5.5.2举例
可以用注解 @FunctionalInterface 自定义一个函数式接口。一旦定义了功能接口,就只能有一个抽象方法。由于您只有一个抽象方法,因此您可以编写多个静态方法和默认方法。
下面是为两个数字相乘而编写的 FunctionalInterface 的编程示例。
@FunctionalInterface
interface FuncInterface {public int multiply(int a, int b);
}
public class Java8 {public static void main(String args[]) {FuncInterface Total = (a, b) -> a * b;System.out.println("Result: "+Total.multiply(30, 60));}
}
相关文章:

【JAVA重要知识 | 第五篇】暴打Java8新特性—(Lambda、方法引用、Stream流、函数式接口、Date Time API、Optional类)
文章目录 5.Java8新特性5.1新特性列表5.2Lambda 表达式5.2.1函数式思想5.2.2举例(1)方式一:创建对象(2)方式二:匿名内部类(3)方式三:Lambda 5.2.3Lambda表达式的标准格式…...

Docker Swarm全解析:实现微服务高可用与故障转移的秘密武器
🐇明明跟你说过:个人主页 🏅个人专栏:《Docker入门到精通》 《k8s入门到实战》🏅 🔖行路有良友,便是天堂🔖 目录 一、基本概念和介绍 1、Docker Swarm 是什么,它与 …...
编码规范(前端)
文章目录 1. 文档说明1.1 编制说明1.2 名词解释 2.前端研发规范2.1 HTML编码规范2.1.1 文档类型2.1.2 语言2.1.3 元数据2.1.4 资源加载2.1.5 页面标题2.1.6 编码风格2.1.7 标签2.1.8 属性2.1.9 语义化 2.2 CSS编码规范2.2.1 文件引用2.2.2 命名-组成元素 知识点 1. 文档说明 1…...

【JavaEE进阶】部署Web项目到Linux服务器
文章目录 🍃前言🍀什么是部署🌲环境配置🚩数据准备🚩程序配置⽂件修改 🎄构建项目并打包🎋上传Jar包到服务器,并运行🚩上传Jar包🚩运行程序🚩开放端口号 &…...

就业班 2401--3.1 Linux Day9--文件查找和压缩
一、文件查找与打包压缩 grep: 文件内容过滤 [rootqfedu.com ~]# grep root /etc/passwd #从/etc/passwd文件中过滤root字段 grep ^root root$ root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin 查找命令 [rootqfedu.com ~]# which ls ali…...

「滚雪球学Java」:JDBC(章节汇总)
🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,助你一臂之力,带你早日登顶🚀,欢迎大家关注&&收藏!持续更新中,up!up!up!…...
RT-DETR改进RepVGG结构:简单但功能强大的卷积神经网络架构
💡本篇内容:RT-DETR改进RepVGG结构:简单但功能强大的卷积神经网络架构 💡🚀🚀🚀本博客 改进源代码改进 适用于 RT-DETR 按步骤操作运行改进后的代码即可 💡本文提出改进 原创 方式:二次创新,RT-DETR专属 应部分读者要求,新增一篇RepVGG 论文理论部分 + 原…...
C#进阶高级语法之LINQ :Lambda 表达式
C# 中的 LINQ (Language Integrated Query) 提供了一种声明性的数据查询和操作方法,它允许开发人员对集合、数据库等数据源进行查询和操作,而不需要编写复杂的循环和手动编码。Lambda 表达式与 LINQ 紧密相关,它提供了一种简洁的方式来定义匿…...
react hook: useCallback
useCallback的主要使用场景在于优化性能,并确保当传递回调函数给子组件时,子组件不会因为父组件的重渲染而重新创建函数。 使用场景 1.当你需要将回调函数传递给子组件时,使用useCallback可以确保子组件在重新渲染时不会不必要地重新创建函数…...

java面试(jvm)
JVM内存模型 细分Eden: java类加载过程?双亲委派机制?一个对象从加载到JVM,再到被GC清除过程? JAVA类加载器:AppClassLoader - ExtClassLoader - BootStrapClassLoader。每种类加载器都有他自己的加载目录…...

自动化测试摸索:python+selenium+pytest(持续更新.....)
一、环境搭建 1、python 安装 下载链接:Python Releases for Windows | Python.org 自己选择合适的版本下载 当下载完毕时,找到该安装程序:python-3.12.2-amd64.exe文件,双击启动安装向导。 为了防止C:盘文件因系统故障或者无…...

C++惯用法之RAII思想: 资源管理
C编程技巧专栏:http://t.csdnimg.cn/eolY7 目录 1.概述 2.RAII的应用 2.1.智能指针 2.2.文件句柄管理 2.3.互斥锁 3.注意事项 3.1.禁止复制 3.2.对底层资源使用引用计数法 3.3.复制底部资源(深拷贝)或者转移资源管理权(移动语义) 4.RAII的优势和挑战 5.总…...
矢量图是什么,有哪些格式的文件
矢量图是一种图形设计中常用的图像类型,与我们日常见到的光栅图像(如JPEG、PNG等)有本质的区别。矢量图基于数学方程和几何元素(如点、线、曲线和形状)来表示图像,而不是像光栅图那样通过像素阵列来表示。这…...

Linux 设置快捷命令
以ll命令为例: 在 Linux 系统上,ll 命令通常不是一个独立的程序,而是 ls 命令的一个别名。 这个别名通常在用户的 shell 配置文件中定义,比如 .bashrc 或 .bash_aliases 文件中。 要在 Debian 上启用 ll 命令,你可以按…...

SpringCloudFeign远程调用
文章目录 1. Feign 是什么2. Feign 的使用2.1 引入依赖2.2 写接口2.3 服务调用方2.4 启动测试 3. Feign 日志配置4. Feign 使用优化5. 注意包扫描问题 1. Feign 是什么 Feign 是一个声明式、模板化的 HTTP 客户端,它是由 Netflix 开发并开源的。Feign 极大地简化了…...
Java中List、Set、Map三种集合之间的区别
Java中List、Set、Map三种集合之间的区别 1. List2. Set3. Map 在Java中,List、Set和Map是三种常见的集合类型,它们之间也有一些重要的区别: 1. List List是有序集合,可以存储重复元素。List的实现类常见有ArrayList、LinkedLis…...
SpringMVC之DispatcherServlet组件
目录 一、SpringMVC的核心处理流程二、DispatcherServlet1、init()方法2、doDispatch()方法3、AbstractAnnotationConfigDispatcherServletInitializer类 一、SpringMVC的核心处理流程 请求到达 DispatcherServlet DispatcherServlet 的请求处理: DispatcherServlet…...

抢商家、夺用户、比低价,抖音、快手、小红书“奇招尽出”
随着流量红利逐渐消退,国内电商平台之间互相内卷已成为了行业常态,而无论是在该领域深耕已久的淘宝、京东、拼多多等电商巨头,还是新跨界而来的抖音、快手、小红书等电商新秀都在不断地进行创新,以便为商家提供更好的服务…...
ChatGPT引领的AI面试攻略系列:AI全栈工程师篇
系列文章目录 AI全栈工程师(本文) 文章目录 系列文章目录一、前言二、面试题1. 基础理论与数据处理2. 机器学习3. 深度学习4. 大模型与迁移学习5. 计算机视觉6. 自然语言处理(NLP)7. 多模态学习8. AI生成内容(AIGC&am…...

上位机图像处理和嵌入式模块部署(qmacvisual配置)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 前面我们谈到了qmacvisual的编译、验证码、用户登录以及流程的编辑,这部分都是基础工作。事实上,除了这些内容之外…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...

如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...

多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...