- 代码传递
- 回调
- 过滤器
当如果有需求, 我们需要将
外部的一段代码
, 在内部执行, 就考虑可以使用匿名类。
package com.other.noname;
/**
* Description:
*
* @date 2022/4/2 20:57
*/
public class Main {
public static void main(String[] args) {
// 现在要计算一段代码的执行时间, 首先需要想到要创建一个工具类TimeUtil
// 首先要想到这一点; 伪代码
// TimeUtil.test(
// // 需要计算时间的代码片段
// int count = 0;
// for (int i = 0; i < 100; i++) {
// count += i;
// }
// )
TimeUtil.test(new TimeUtil.Block() {
@Override
public void execute() {
// 在这里写我们需要执行的代码块
for (int i = 0; i < 1000000; i++) {
System.out.println(i);
}
}
});
}
}
public class TimeUtil {
public interface Block {
void execute();
}
// 由于我们的test方法,需要接收一个代码片段, 在我们的工具类中进行时间计算;
// 所以我们定义一个可以接收代码片段的参数
public static void test(Block block) {
long start = System.currentTimeMillis();
block.execute(); // 最终实际调用了Block的匿名实现类中的execute方法
long end = System.currentTimeMillis();
System.out.println("耗时: " + (end - start) / 1000.0 + "秒");
}
}
package com.other.noname;
/**
* Description: 测试匿名类用途2, 回调
*
* 模拟网络请求
*
* @date 2022/4/2 21:31
*/
public class NetworkUtil {
public interface Block {
void success(Object response);
void failure();
}
public static void get(String url, Block block) {
// 1. 根据url发送一个异步请求(开启一条子线程)
// ......
// 2. 请求完毕后
boolean result = !url.contains("666");
if (result) {
// false, 不包含666, 表示请求失败
block.failure();
} else {
Object response = "我是响应体";
block.success(response);
}
}
}
@Test
public void test02() {
/*
这里就展示出了匿名类的回调, 和代码传递很相似
当调用NetworkUtil的get方法时, 我们先将Block的实现类以及它的实现方法实现好, 并作为实参传递给get方法,执行请求
请求过去之后, 由服务器的响应来判断是否请求成功; 此时再回调我们实现类中的实现方法 success 或 failure
*/
NetworkUtil.get("http://www.it666.com", new NetworkUtil.Block() {
@Override
public void success(Object response) {
System.out.println("请求成功!" + response);
}
@Override
public void failure() {
System.out.println("请求失败!");
}
});
}
@Test
public void test03() {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
Collection<Integer> filterCollection = FilterUtil.getFilterCollection(list, new FilterUtil.Filter<Integer>() {
@Override
public boolean test(Integer integer) {
return integer > 2;
}
});
filterCollection.forEach(System.out::println);
}
public class FilterUtil {
public interface Filter<T> {
boolean test(T t);
}
public static <T> Collection<T> getFilterCollection(Collection<T> collection, Filter<T> filter) {
List<T> list = new ArrayList<>();
collection.forEach(item -> {
if (filter.test(item)) {
list.add(item);
}
});
return list;
}
}
我们可以把Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)
public class LambdaDemo {
public static void main(String[] args) {
//开启一个线程
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("新线程执行代码");
}
}).start();
}
分析上面代码
new Thread().start()
的方式启动一个线程时,我们做了如下3件事情:
- 定义了一个没有名字的类(匿名类) – new Thread(Runnable接口)
- 这个类的参数是Runnable 接口
- 我们通过 new Runnable(){…}的方式创建了这个类,并重写了该接口的 run() 方法
- run() 方法 (参数情况)
- 以及run方法 {…}方法体中执行的代码
- Lambda表达式体现的是函数式编程思想,
只需要将要执行的代码放到函数中即可(函数就是类中的方法)
;- Lambda表达式就是一个匿名函数,我们只需要将执行的代码放到 Lambda 表达式中即可。
Lambda省去面向对象的条条框框,Lambda的标准格式由3部分组成:
(参数类型 参数名称) -> {
方法体;
return 返回值;
}
格式说明
- (参数类型 参数名称):(接口方法)重写方法的参数列表部分
- {…}:重写方法的方法体,即要执行的代码部分
- –>:箭头,无实际含义,起到连接参数列表和方法体的作用
Lambda 表达式的省略规则
- 小括号中的参数类型可以省略。
- 如果小括号中只有一个参数,那么可以省略小括号。
- 如果大括号中只有一条语句,那么可以同时省略大括号、return关键字及语句分号。
使用Lambda优化Demo
public class LambdaDemo {
public static void main(String[] args) {
//匿名内部类方式
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("新线程执行代码了");
}
}).start();
//体验Lambda表达式: () -> {xxxx}, ()无参数是和Runable中run方法的参数对应的
// {xxx}是重写run方法的方法体
new Thread(() ->{
System.out.println("Lambda表达式执行了");
}).start();
}
}
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
import org.junit.Test;
import java.util.Comparator;
/**
* Lambda表达式的使用举例
*/
public class LambdaTest {
@Test
public void test(){
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("长安欢迎您");
}
};
r1.run();
System.out.println("+++++++++++++++++++++++++|");
Runnable r2 = () -> System.out.println("长安欢迎您");
r2.run();
}
@Test
public void test2(){
Comparator<Integer> c1 = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return Integer.compare(o1,o2);
}
};
int compare1 = c1.compare(8,16);
System.out.println(compare1);
System.out.println("+++++++++++++++++++++++");
//Lambda表达式的写法
// int compare(T o1, T o2);
Comparator<Integer> c2 = (o1,o2) -> Integer.compare(o1,o2);
int compare2 = c2.compare(28,35);
System.out.println(compare2);
System.out.println("+++++++++++++++++++++++++++");
//方法引用(暂时可以不关注,后面会介绍)
Comparator<Integer> c3 = Integer :: compare;
int compare3 = c3.compare(28,35);
System.out.println(compare3);
}
}
@FunctionalInterface
public interface Comparator<T> {
int compare(T o1, T o2);
}
import org.junit.Test;
import java.util.ArrayList;
import java.util.function.Consumer;
/**
* Lambda表达式的使用
*
* 1.举例: (o1,o2) -> Integer.compare(o1,o2);
* 2.格式:
* -> :lambda操作符 或 箭头操作符
* ->左边:lambda形参列表 (其实就是接口中的抽象方法的形参列表)
* ->右边:lambda体 (其实就是重写的抽象方法的方法体)
*
* 3.Lambda表达式的使用:(分为6种情况介绍)
*/
public class LambdaTest1 {
//语法格式一:无参,无返回值
@Test
public void test(){
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("长安欢迎您");
}
};
r1.run();
System.out.println("+++++++++++++++++++++++++|");
Runnable r2 = () -> System.out.println("长安欢迎您");
r2.run();
}
//语法格式二:Lambda 需要一个参数,但是没有返回值。
@Test
public void test2(){
Consumer<String> con = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
con.accept("善与恶的区别是什么?");
System.out.println("+++++++++++++++++++");
Consumer<String> c1 = (String s) -> {
System.out.println(s);
};
c1.accept("先天人性无善恶,后天人性有善恶。");
}
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
//语法格式三:数据类型可以省略,因为可由编译器推断得出,称为“类型推断”
@Test
public void test3(){
Consumer<String> c1 = (String s) -> {
System.out.println(s);
};
c1.accept("先天人性无善恶,后天人性有善恶。");
System.out.println("---------------------");
Consumer<String> c2 = (s) -> {
System.out.println(s);
};
c2.accept("如果没有邪恶的话我们怎么会知道人世间的那些善良呢?");
}
@Test
public void test4(){
ArrayList<String> list = new ArrayList<>();//类型推断
int[] arr = {1,2,3};//类型推断
}
}
import org.junit.Test;
import java.util.Comparator;
import java.util.function.Consumer;
/**
* Lambda表达式的使用
*
* 1.举例: (o1,o2) -> Integer.compare(o1,o2);
* 2.格式:
* -> :lambda操作符 或 箭头操作符
* ->左边:lambda形参列表 (其实就是接口中的抽象方法的形参列表)
* ->右边:lambda体 (其实就是重写的抽象方法的方法体)
*
* 3.Lambda表达式的使用:(分为6种情况介绍)
*
* 总结:
* ->左边:lambda形参列表的参数类型可以省略(类型推断);如果lambda形参列表只有一个参数,其一对()也可以省略
* ->右边:lambda体应该使用一对{}包裹;如果lambda体只有一条执行语句(可能是return语句),省略这一对{}和return关键字
*/
public class LambdaTest1 {
//语法格式四:Lambda若只需要一个参数时,参数的小括号可以省略
@Test
public void test5(){
Consumer<String> c1 = (s) -> {
System.out.println(s);
};
c1.accept("先天人性无善恶,后天人性有善恶。");
System.out.println("---------------------");
Consumer<String> c2 = s -> {
System.out.println(s);
};
c2.accept("如果没有邪恶的话我们怎么会知道人世间的那些善良呢?");
}
//语法格式五:Lambda需要两个或以上的参数,多条执行语句,并且可以有返回值
@Test
public void test6(){
Comparator<Integer> c1 = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
}
};
System.out.println(c1.compare(15,23));
System.out.println("\\\\\\\\\\\\\\\\\\\\\\\\\\");
Comparator<Integer> com2 = (o1,o2) -> {
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
};
System.out.println(com2.compare(16,8));
}
//语法格式六:当Lambda体只有一条语句时,return与大括号若有,都可以省略
@Test
public void test7(){
Comparator<Integer> c1 = (o1,o2) -> {
return o1.compareTo(o2);
};
System.out.println(c1.compare(16,8));
System.out.println("\\\\\\\\\\\\\\\\\\\\\\\\\\");
Comparator<Integer> c2 = (o1,o2) -> o1.compareTo(o2);
System.out.println(c2.compare(17,24));
}
@Test
public void test8(){
Consumer<String> c1 = s -> {
System.out.println(s);
};
c1.accept("先天人性无善恶,后天人性有善恶。");
System.out.println("---------------------");
Consumer<String> c2 = s -> System.out.println(s);
c2.accept("如果没有邪恶的话我们怎么会知道人世间的那些善良呢?");
}
}
方法的参数或局部变量类型必须为接口,才能使用Lambda
/*
* 4.Lambda表达式的本质:作为函数式接口的实例
*
* 5. 如果一个接口中,只声明了一个抽象方法,则此接口就称为函数式接口。我们可以在一个接口上使用 @FunctionalInterface 注解,
* 这样做可以检查它是否是一个函数式接口。
*
*/
/**
* 自定义函数式接口
*/
public interface MyInterFace {
void method();
// void method2();
}
java.util.function
包下定义了Java 8 的丰富的函数式接口函数式接口 | 参数类型 | 返回类型 | 用途 |
---|---|---|---|
Consumer 消费型接口 | T | void | 对类型为T的对象应用操作,包含方法:void accept(T t) |
Supplier 供给型接口 | 无 | T | 返回类型为T的对象,包含方法:T get() |
Function 函数型接口 | T | R | 对类型为T的对象应用操作,并返回结果。结果是R类型的对象。包含方法:R apply(T t) |
Predicate 断定型接口 | T | boolean | 确定类型为T的对象是否满足某约束,并返回boolean 值。包含方法:boolean test(T t) |
BiFunction | T, U | R | 对类型为T,U参数应用操作,返回R类型的结果。包含方法为:R apply(T t,U u) ; |
UnaryOperator (Function子接口) | T | T | 对类型为T的对象进行一元运算,并返回T类型的结果。包含方法为:T apply(T t) ; |
BinaryOperator (BiFunction子接口) | T,T | T | 对类型为T的对象进行二元运算,并返回T类型的结果。包含方法为:T apply(T t1,T t2) ; |
BiConsumer | T,U | void | 对类型为T,U参数应用操作。包含方法为:void accept(Tt,Uu) |
BiPredicate | T,U | boolean | 包含方法为:boolean test(Tt,Uu) |
ToIntFunction | T | int | 计算int 值的函数 |
ToLongFunction | T | long | 计算long 值的函数 |
ToDoubleFunction | T | double | 计算double 值的函数 |
IntFunction | int | R | 参数为int 类型的函数 |
LongFunction | long | R | 参数为long 类型的函数 |
DoubleFunction | double | R | 参数为double 类型的函数 |
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
/**
* java内置的4大核心函数式接口
*
* 消费型接口 Consumer void accept(T t)
* 供给型接口 Supplier T get()
* 函数型接口 Function R apply(T t)
* 断定型接口 Predicate boolean test(T t)
*/
public class LambdaTest2 {
// ----消费型接口 Consumer void accept(T t)
public void happyTime(double money, Consumer<Double> con) {
con.accept(money);
}
@Test
public void test(){
happyTime(30, new Consumer<Double>() {
@Override
public void accept(Double aDouble) {
System.out.println("熬夜太累了,点个外卖,价格为:" + aDouble);
}
});
System.out.println("+++++++++++++++++++++++++");
//Lambda表达式写法
happyTime(20, money -> System.out.println("熬夜太累了,吃口麻辣烫,价格为:" + money));
}
// -----供给型接口 Supplier T get()
//根据给定的规则,过滤集合中的字符串。此规则由Predicate的方法决定
public List<String> filterString(List<String> list, Predicate<String> pre){
ArrayList<String> filterList = new ArrayList<>();
for(String s : list){
if(pre.test(s)){
filterList.add(s);
}
}
return filterList;
}
@Test
public void test2(){
List<String> list = Arrays.asList("长安","上京","江南","渝州","凉州","兖州");
List<String> filterStrs = filterString(list, new Predicate<String>() {
@Override
public boolean test(String s) {
return s.contains("州");
}
});
System.out.println(filterStrs);
List<String> filterStrs1 = filterString(list,s -> s.contains("州"));
System.out.println(filterStrs1);
}
}
T get();
/**
* Description: 供给型接口
*
* T get();
*
* 有时使用 Supplier 传参,可以避免代码的浪费执行(有必要的时候再执行)
*/
public class SupplierTest {
/*
现在有个需求, 如果第一个字符串不为空, 则返回第一个字符串, 否则返回第二个字符串
*/
public static void main(String[] args) {
System.out.println(getFirstNotEmptyString("Jack", makeString()));
}
public static String getFirstNotEmptyString(String str1, String str2) {
if (str1 != null && str1.length() > 0) return str1;
if (str2 != null && str2.length() > 0) return str2;
return null;
}
private static String makeString() {
System.out.println("makeString");
return String.format("%d %d %d", 1, 2, 3);
}
}
此时发现, 如果第一个参数不为空之后, 还调用了makeString()方法, 明显存在浪费调用; 所以可以使用Supplier来优化
/**
* Description: 供给型接口
*
* T get();
*
* 有时使用 Supplier 传参,可以避免代码的浪费执行(有必要的时候再执行)
*
* @date 2022/4/3 18:58
*/
public class SupplierTest {
/*
现在有个需求, 如果第一个字符串不为空, 则返回第一个字符串, 否则返回第二个字符串
*/
public static void main(String[] args) {
//System.out.println(getFirstNotEmptyString("Jack", makeString()));
System.out.println(getFirseNotEmptyString("Jack", new Supplier<String>() {
@Override
public String get() {
return makeString();
}
}));
//System.out.println(getFirseNotEmptyString("Jack", () -> makeString()));
//System.out.println(getFirseNotEmptyString("Jack", SupplierTest::makeString));
}
// public static String getFirstNotEmptyString(String str1, String str2) {
// if (str1 != null && str1.length() > 0) return str1;
// if (str2 != null && str2.length() > 0) return str2;
// return null;
// }
// 优化
public static String getFirseNotEmptyString(String str1, Supplier<String> supplier) {
if (str1 != null && str1.length() > 0) return str1;
String str2 = supplier.get();
if (str2 != null && str2.length() > 0) return str2;
return null;
}
private static String makeString() {
System.out.println("makeString");
return String.format("%d %d %d", 1, 2, 3);
}
}
// 此时就完成了优化, 延迟了makeString()方法的调用
void accept(T t)
public static void main(String[] args) {
/*
Consumer这个函数式接口, 用来接收我们提供的元素, 具体操作这些元素由调用者来决定
*/
Integer[] nums = {1, 2, 3, 4};
// 比如, 我们要遍历所有元素
for (Integer num : nums) {
System.out.println(num);
}
// 比如, 我们要遍历所有都+100的元素
for (Integer num : nums) {
System.out.println(num + 100);
}
// 上面的代码, 实现了需求, 但是具体对元素的操作是千变万化的, eg: 遍历出偶数/基数元素等,我们还需要再写不同的逻辑进行处理
// 此时可以使用Consumer函数式接口
}
public class ConsumerTest {
public static void main(String[] args) {
/*
Consumer这个函数式接口, 用来接收我们提供的元素, 具体操作这些元素由调用者来决定
*/
Integer[] nums = {1, 2, 3, 4};
// 比如, 我们要遍历所有元素
for (Integer num : nums) {
System.out.println(num);
}
// 比如, 我们要遍历所有都+100的元素
for (Integer num : nums) {
System.out.println(num + 100);
}
System.out.println("--------------------------");
// 上面的代码, 实现了需求, 但是具体对元素的操作是千变万化的, eg: 遍历出偶数/基数元素等,我们还需要再写不同的逻辑进行处理
// 此时可以使用Consumer函数式接口
forEach(nums, System.out::println);
forEach(nums, integer -> System.out.println(integer + 100));
}
// public static void forEach(Integer[] nums, Consumer consumer) {
// if (nums == null || consumer == null) return;
// for (Integer num : nums) {
// consumer.accept(num); // 这里是Consumer的接口方法, 具体的实现方法, 由调用者来决定
// }
// }
// 对上面代码的优化, 变成泛型方法, 增加通用性
public static <T> void forEach(T[] nums, Consumer<T> consumer) {
if (nums == null || consumer == null) return;
for (T num : nums) {
consumer.accept(num); // 这里是Consumer的接口方法, 具体的实现方法, 由调用者来决定
}
}
}
andThen的使用
public static void main(String[] args) {
int[] nums = { 11, 33, 44, 88, 77, 66 };
forEach(nums, (n) -> {
String result = ((n & 1) == 0) ? "偶数" : "奇数";
System.out.println(n + "是" + result);
}, (n) -> {
String result = ((n % 3) == 0) ? "能" : "不能";
System.out.println(n + result + "被3整除");
});
}
static void forEach(int[] nums, Consumer<Integer> c1, Consumer<Integer> c2) {
if (nums == null || c1 == null || c2 == null) return;
for (int n : nums) {
// 相当于先执行c1的任务, 然后执行c2的任务, 执行完后进入下一轮循环
c1.andThen(c2).accept(n);
}
}
11是奇数
11不能被3整除
33是奇数
33能被3整除
44是偶数
44不能被3整除
88是偶数
88不能被3整除
77是奇数
77不能被3整除
66是偶数
66能被3整除
boolean test(T t);
/**
* Description: 应用常见, 过滤操作
*
* boolean test(T t);
*
* @author guizy
* @date 2022/4/3 19:31
*/
public class PredicateTest {
public static void main(String[] args) {
/*
对数组中{11, 22, 33, 44, 55, 66}的偶数用_进行拼接
*/
Integer[] nums = {11, 22, 33, 44, 55, 66};
join(nums, new Predicate<Integer>() {
@Override
public boolean test(Integer integer) {
return integer % 2 == 0; // 表示integer为偶数的时候, 才进行拼接
}
});
System.out.println("-------------------");
join(nums, item -> item % 2 == 0);
}
public static void join(Integer[] nums, Predicate<Integer> predicate) {
if (nums == null || predicate == null) return;
for (Integer num : nums) {
if (predicate.test(num)) {
System.out.println(num + "_");
}
}
}
}
R applay(T t);
/**
* Description: Fucntion 类型转换
*
* R apply(T t);
*
*/
public class FunctionTest {
public static void main(String[] args) {
/*
需求, 将传入的字符串数字的数组, 求和
*/
System.out.println(getSum(new String[]{"1", "2", "3"}, new Function<String, Integer>() {
@Override
public Integer apply(String s) {
return Integer.valueOf(s);
}
}));
System.out.println(getSum(new String[]{"1", "2", "3"}, Integer::valueOf));
}
public static int getSum(String[] array, Function<String, Integer> function) {
if (array == null || function == null) return 0;
int result = 0;
for (String str : array) {
result += function.apply(str);
}
return result;
}
}
当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用
实现接口的抽象方法的参数列表和返回值类型,必须与方法引用的方法的参数列表和返回值类型保持一致!
1、Employee类
@Data
public class Employee {
private int id;
private String name;
private int age;
private double salary;
}
2、测试类
import org.junit.Test;
import java.io.PrintStream;
import java.util.Comparator;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* 方法引用的使用
*
* 1.使用情境:当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!
*
* 2.方法引用,本质上就是Lambda表达式,而Lambda表达式作为函数式接口的实例。所以
* 方法引用,也是函数式接口的实例。
*
* 3. 使用格式: 类(或对象) :: 方法名
*
* 4. 具体分为如下的三种情况:
* 情况1 对象 :: 非静态方法
* 情况2 类 :: 静态方法
*
* 情况3 类 :: 非静态方法
*
* 5. 方法引用使用的要求:要求接口中的抽象方法的形参列表和返回值类型与方法引用的方法的
* 形参列表和返回值类型相同!(针对于情况1和情况2)
*/
public class MethodRefTest {
// 情况一:对象 :: 实例方法
//Consumer中的void accept(T t)
//PrintStream中的void println(T t)
@Test
public void test() {
Consumer<String> c1 = str -> System.out.println(str);
c1.accept("兖州");
System.out.println("+++++++++++++");
PrintStream ps = System.out;
Consumer<String> c2 = ps::println;
c2.accept("xian");
}
//Supplier中的T get()
//Employee中的String getName()
@Test
public void test2() {
Employee emp = new Employee(004,"Nice",19,4200);
Supplier<String> sk1 = () -> emp.getName();
System.out.println(sk1.get());
System.out.println("*******************");
Supplier<String> sk2 = emp::getName;
System.out.println(sk2.get());
}
}
1、Employee类——同上
2、测试类
import org.junit.Test;
import java.util.Comparator;
import java.util.function.Function;
public class MethodRefTest {
// 情况二:类 :: 静态方法
//Comparator中的int compare(T t1,T t2)
//Integer中的int compare(T t1,T t2)
@Test
public void test3() {
Comparator<Integer> com1 = (t1, t2) -> Integer.compare(t1,t2);
System.out.println(com1.compare(21,20));
System.out.println("+++++++++++++++");
Comparator<Integer> com2 = Integer::compare;
System.out.println(com2.compare(15,7));
}
//Function中的R apply(T t)
//Math中的Long round(Double d)
@Test
public void test4() {
Function<Double,Long> func = new Function<Double, Long>() {
@Override
public Long apply(Double d) {
return Math.round(d);
}
};
System.out.println("++++++++++++++++++");
Function<Double,Long> func1 = d -> Math.round(d);
System.out.println(func1.apply(14.1));
System.out.println("++++++++++++++++++");
Function<Double,Long> func2 = Math::round;
System.out.println(func2.apply(17.4));
}
}
1、Employee类——同上
2、测试类
import org.junit.Test;
import java.util.Comparator;
import java.util.function.BiPredicate;
import java.util.function.Function;
public class MethodRefTest {
// 情况三:类 :: 实例方法 (有难度)
// Comparator中的int comapre(T t1,T t2)
// String中的int t1.compareTo(t2)
@Test
public void test5() {
Comparator<String> com1 = (s1,s2) -> s1.compareTo(s2);
System.out.println(com1.compare("abc","abd"));
System.out.println("++++++++++++++++");
Comparator<String> com2 = String :: compareTo;
System.out.println(com2.compare("abd","abm"));
}
//BiPredicate中的boolean test(T t1, T t2);
//String中的boolean t1.equals(t2)
@Test
public void test6() {
BiPredicate<String,String> pre1 = (s1, s2) -> s1.equals(s2);
System.out.println(pre1.test("MON","MON"));
System.out.println("++++++++++++++++++++");
BiPredicate<String,String> pre2 = String :: equals;
System.out.println(pre2.test("MON","MON"));
}
// Function中的R apply(T t)
// Employee中的String getName();
@Test
public void test7() {
Employee employee = new Employee(007, "Ton", 21, 8000);
Function<Employee,String> func1 = e -> e.getName();
System.out.println(func1.apply(employee));
System.out.println("++++++++++++++++++++++++");
Function<Employee,String> f2 = Employee::getName;
System.out.println(f2.apply(employee));
}
}
格式:ClassName::new
与函数式接口相结合,自动与函数式接口中方法兼容。
可以把构造器引用赋值给定义的方法,要求构造器参数列表要与接口中抽象方法的参数列表一致!且方法的返回值即为构造器对应类的对象。
1、Employee类——同上
2、测试类
import org.junit.Test;
import java.util.Arrays;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* 一、构造器引用
* 和方法引用类似,函数式接口的抽象方法的形参列表和构造器的形参列表一致。
* 抽象方法的返回值类型即为构造器所属的类的类型
*
* 二、数组引用
* 可以把数组看做是一个特殊的类,则写法与构造器引用一致。
*/
public class MethodRefTest {
//构造器引用
//Supplier中的T get()
//Employee的空参构造器:Employee()
@Test
public void test() {
Supplier<Employee> sup = new Supplier<Employee>() {
@Override
public Employee get() {
return new Employee();
}
};
System.out.println("+++++++++++++++++++");
Supplier<Employee> sk1 = () -> new Employee();
System.out.println(sk1.get());
System.out.println("+++++++++++++++++++");
Supplier<Employee> sk2 = Employee::new;
System.out.println(sk2.get());
}
//Function中的R apply(T t)
@Test
public void test2() {
Function<Integer, Employee> f1 = id -> new Employee(id);
Employee employee = f1.apply(7793);
System.out.println(employee);
System.out.println("+++++++++++++++++++");
Function<Integer, Employee> f2 = Employee::new;
Employee employee1 = f2.apply(4545);
System.out.println(employee1);
}
//BiFunction中的R apply(T t,U u)
@Test
public void test3() {
BiFunction<Integer, String, Employee> f1 = (id, name) -> new Employee(id, name);
System.out.println(f1.apply(2513, "Fruk"));
System.out.println("*******************");
BiFunction<Integer, String, Employee> f2 = Employee::new;
System.out.println(f2.apply(9526, "Bon"));
}
//数组引用
//Function中的R apply(T t)
@Test
public void test4() {
Function<Integer, String[]> f1 = length -> new String[length];
String[] arr1 = f1.apply(7);
System.out.println(Arrays.toString(arr1));
System.out.println("+++++++++++++++++++");
Function<Integer, String[]> f2 = String[]::new;
String[] arr2 = f2.apply(9);
System.out.println(Arrays.toString(arr2));
}
}