1.lambda表达式:
加入lambda之后,很多写法都变得简单起来,如创建一个线程对象
new Thread(new Runnable() {
@Override
public void run() {
System.out.print("Hello");
}
});
lambda写法:
new Thread(() -> System.out.print("Hello"));
单独将lambda拎出来:
Runnable runnable = () -> System.out.print("Hello");
其实lambda代表的就是一个接口的实现而已(匿名内部类)。
而这种接口也叫函数式接口,会有@FunctionalInterface注解进行编译时检查。
或者直接把lambda看成一个方法,上述的 () -> System.out.print("Hello") 就是代表一个无入参、无返回值的一个方法(等同于public void run() {System.out.print("Hello")}),而Runnable runnable则是指向这个方法(类似函数指针),需要调用这个方法时,调用runnable.run()即可.
当有一个参数、无返回值则是Consumer<T>
// 对printStream对象的void print(String s)方法的引用
PrintStream printStream = System.out;
Consumer<String> consumer = printStream::print;
consumer.accept("Hello");
// 输出
Hello
以上为java.util.function包下的部分接口,剩余的基本上就是指定泛型类型的函数接口了,例如LongConsumer,无泛型,其实就是指定入参只能是Long。
上述已经代表了大部分的函数可以表示的形式了(值得注意的是,三个及以上的入参的函数式接口JDK并没有提供,需要时要自定义实现,实际上也很少用到)。
方法有静态方法(static)和非静态方法,但函数式接口关注的仅是入参、出参类型和个数而已:
public Class Test {
public Long noStaticFoo(String str) {...}
public static Long staticFoo(String str) {...}
public static void main() {
// 静态方法,类::
Function<String, Long> staticFoo = Test::staticFoo;
Long apply = staticFoo.apply("100");
// 非静态方法,实例对象::
Test test = new Test();
Function<String, Long> noStaticFoo = test::noStaticFoo;
Long apply2 = noStaticFoo.apply("100");
/* 这种可以理解成两个入参、除了原来方法的入参外,还要指明实例对象(因为这是一个实例方法)*/
BiFunction<Test, String, Long> noStaticFooTest = Test::noStaticFoo;
Long apply3 = noStaticFooTest.apply(test, "100");
}
}
java8异步方法调用写法
public class UserHttpService {
public User getById(Long id) {
...
return user;
}
}
public class AsyncExecutor {
// 线程池,建议恰当配置(拒绝策略建议CallerRunsPolicy)和使用框架注入
private ExecutorService executorService = Executors.newFixedThreadPool(10);
/**
* 单个入参,有返回值的异步执行方法 , public User getById(Long id)
*
* @param method 要执行的方法,如 , userHttpService::getById
* @param param 入参值,如 100
* @param <P> 入参类型,如 Long
* @param <R> 返回值类型,如 User
* @return Future对象,用以判断是否执行结束、获取返回结果
*/
public <P, R> Future<R> async(Function<P, R> method, P param) {
return executorService.submit(() -> method.apply(param));
}
}
public class A {
private AsyncExecutor asyncExecutor;
private UserHttpService userHttpService;
public void foo() {
...
// 异步调用
Future<User> userFuture = asyncExecutor.async(userHttpService::getById, id);
... 其他操作(如再发起http请求)
// 获取结果
User user = userFuture.get();
...
}
}
public class AsyncExecutor {
// 线程池,建议恰当配置(拒绝策略建议CallerRunsPolicy)和使用框架注入
private ExecutorService executorService = Executors.newFixedThreadPool(10);
/**
* 无入参,无返回值的异步执行方法 , void noStaticFoo()
*
* @param method 要执行的方法,如 user::noStaticFoo;
* @return Future对象,用以判断是否执行结束
*/
public Future async(Runnable method) {
return executorService.submit(method);
}
/**
* 有单个入参,无返回值的异步执行方法,如 void noStaticFoo(Long id)
*
* @param method 要执行的方法,如, user::noStaticFoo
* @param param 方法执行的入参,如id
* @param <P> 入参类型,如Long
* @return Future对象,用以判断是否执行结束
*/
public <P> Future async(Consumer<P> method, P param) {
return executorService.submit(() -> method.accept(param));
}
/**
* 有两个参数但是无返回值的异步执行方法, 如void noStaticFoo(Long id,Entity entity)
*
* @param method 要执行的方法,如 , user::noStaticFoo
* @param param1 第一个入参值,如id
* @param param2 二个入参值,如entity
* @param <P1> 第一个入参类型
* @param <P2> 第二个入参类型
* @return Future对象,用以判断是否执行结束
*/
public <P1, P2> Future async(BiConsumer<P1, P2> method, P1 param1, P2 param2) {
return executorService.submit(() -> method.accept(param1, param2));
}
/**
* 无参数有返回值的异步执行方法 , Entity noStaticFoo()
*
* @param method 要执行的方法,如 , user::noStaticFoo
* @param <R> 返回值类型,如 Entity
* @return Future对象,用以判断是否执行结束、获取返回结果
*/
public <R> Future<R> async(Supplier<R> method) {
return executorService.submit(method::get);
}
/**
* 单个入参,有返回值的异步执行方法 , Entity noStaticFoo(Long id)
*
* @param method 要执行的方法,如 , user::noStaticFoo
* @param param 入参值,如 id
* @param <P> 入参类型,如Long
* @param <R> 返回值类型,如 Entity
* @return Future对象,用以判断是否执行结束、获取返回结果
*/
public <P, R> Future<R> async(Function<P, R> method, P param) {
return executorService.submit(() -> method.apply(param));
}
/**
* 两个入参,有返回值的异步执行方法 , Entity noStaticFoo(Long id)
*
* @param method 要执行的方法,如 , user::noStaticFoo
* @param param1 第一个入参值,如id
* @param param2 二个入参值,如entity
* @param <P1> 第一个入参类型
* @param <P2> 第二个入参类型
* @param <R> 返回值类型,如 Entity
* @return Future对象,用以判断是否执行结束、获取返回结果
*/
public <P1, P2, R> Future<R> async(BiFunction<P1, P2, R> method, P1 param1, P2 param2) {
return executorService.submit(() -> method.apply(param1, param2));
}
}
JDK1.8 有提供CompletableFuture,也是类似异步处理的方法,默认线程池为ForkJoinPool(默认最大工作线程数=CPU总核心数-1),该线程池擅长于计算密集型任务,IO密集型任务请尽量使用自己合理配置的线程池。
函数式接口
函数式接口就是只定义一个抽象方法的接口.例如:Comparator和Runnable 和 Predicate 和 FileFilter
接口现在还可以拥有默认方法(即在类没有对方法进行实现时, 其主体为方法提供默认实现的方法)。
哪怕有很多默认方法,只要接口只定义了一个抽象 方法,它就仍然是一个函数式接口。
注意(函数式接口):
函数式接口中可以额外定义多个抽象方法,但这些抽象方法签名必须和Object的public方法一样
接口最终有确定的类实现, 而类的最终父类是Object。Comparator有两个抽象方法(compare和equals方法) ,Comparator类的equals方法名和Object的equals方法一样.
所有类默认继承Object,所以该类已有了Object的equals方法,相当于重写了equals方法。
用函数式接口可以干什么呢?
Lambda表达式允许你直接以内联的形式为函数式接口的抽象方法提供实现,并把整个表达式作为函数式接口的实例(具体说来,是函数式接口一个具体实现 的实例)。
你用匿名内部类也可以完成同样的事情,只不过比较笨拙:需要提供一个实现,然后 再直接内联将它实例化。
下面的代码是有效的,因为Runnable是一个只定义了一个抽象方法run 的函数式接口:
函数描述符:
函数式接口的抽象方法的签名基本上就是Lambda表达式的签名。我们将这种抽象方法叫作 函数描述符。
例如,Runnable接口可以看作一个什么也不接受什么也不返回(void)的函数的 签名,因为它只有一个叫作run的抽象方法,
这个方法什么也不接受,什么也不返回(void)。
Java重用了函数式接口提 供的标准类型,并将其映射成一种形式的函数类型。
Java 8的库设计师帮你在java.util.function包中引入了几个新的函数式接:Predicate、Consumer 、Function
https://blog.csdn.net/a879611951/article/details/80104014 四大核心函数接口
Function<T, R>
T:入参类型,R:出参类型
调用方法:R apply(T t);
定义函数示例:Function<Integer, Integer> func = p -> p * 10; // 输出入参的10倍
调用函数示例:func.apply(10); // 结果100
例如:
Function<Integer, Integer> fun1 = n->n*2 ;
fun1.apply(3);
public static void main(String[] args) {
List<Integer> weights = Arrays.asList(7, 3, 4, 10);
Function<Integer, Apple> intConsumer = Apple::new;
List<Apple> apples = map(weights,Apple::new);
System.out.println(JSON.toJSONString(apples));
}
public static List<Apple> map(List<Integer> list, Function<Integer, Apple> f) {
List<Apple> result = new ArrayList<>();
for (Integer e : list) {
Apple apply = f.apply(e);
result.add(f.apply(e));
}
return result;
}
运行结果:[{"weight":7},{"weight":3},{"weight":4},{"weight":10}]
Supplier<T>
T:出参类型;没有入参
调用方法:T get();
定义函数示例:Supplier<Integer> supplier= () -> 100; // 常用于业务“有条件运行”时,符合条件再调用获取结果的应用场景;运行结果须提前定义,但不运行。
调用函数示例:supplier.get();
例如:
Supplier<String> supplier = String::new;
System.out.println(supplier.get());//""
Supplier<Emp> supplierEmp = Emp::new;
Emp emp = supplierEmp.get();
emp.setName("dd");
System.out.println(emp.getName());//dd
Consumer<T>
T:入参类型;没有出参
调用方法:void accept(T t);
定义函数示例:Consumer<String> consumer= p -> System.out.println(p); // 因为没有出参,常用于打印、发送短信等消费动作
调用函数示例:consumer.accept("18800008888");
Predicate<T>
用于判断, 定义的函数只会返回true或false
例如: Predicate<String> isEmpty = String::isEmpty;
Predicate<String> isEmpty1 = (String str) ->str.isEmpty();
T:入参类型;出参类型是Boolean
调用方法:boolean test(T t);
定义函数示例:Predicate<Integer> predicate = p -> p % 2 == 0; // 判断是否、是不是偶数
调用函数示例:predicate.test(100); // 运行结果true
Consumer<String> aa= a-> System.out.println(a);
Consumer<String> aa1= System.out::println;
getLowCaloricDishesNamesInJava8(Dish.menu).forEach(aa);
public static List<String> getLowCaloricDishesNamesInJava8(List<Dish> dishes){
//Dish类 calories变量 getCalories 是calories变量的get方法
Comparator<Dish> comparing = comparing(Dish::getCalories);
Function<Dish, String> getName = Dish::getName;
List<String> collect = dishes.stream()
.filter(d -> d.getCalories() < 400)
.sorted(comparing(Dish::getCalories))
.map(Dish::getName)
.collect(toList());
return collect;
}
https://www.cnblogs.com/lijingran/p/8708037.html java编程Consumer和Predicate案例
//修改属性的值
@Test
public void test(){
UserT userT = new UserT("zm");
//接受一个参数
Consumer<UserT> userTConsumer = userT1 -> userT1.setName("zmChange");};
userTConsumer.accept(userT);
logger.info(userT.getName());//输出zmChange
}
public class PredicateConsumerDemo {
public static Student updateStudentFee(Student student, Predicate<Student> predicate, Consumer<Student>
){
if (predicate.test(student)){
consumer.accept(student);
}
return student;
}
}
public class Test {
public static void main(String[] args) {
Student student1 = new Student("Ashok","Kumar", 9.5);
student1 = updateStudentFee(student1, student -> student.grade > 8.5, student -> student.feeDiscount = 30.0);
student1.printFee();
Student student2 = new Student("Rajat","Verma", 8.0);
student2 = updateStudentFee(student2, student -> student.grade >= 8, student -> student.feeDiscount = 20.0);
student2.printFee();
}
}