四大函数简述(简写用lambda表达式):
java.util.function , Java 内置核心四大函数式接口,可以使用lambda表达式
消费型接口,有一个输入参数,没有返回值
public static void main(String[] args) {
// Consumer<String> consumer=new Consumer<String>(){
// @Override
// public void accept(String s){
//
// }
// };
// 简写
Consumer<String> consumer = s -> { System.out.println(s);};
consumer.accept("abc");
}
//-----------------------------------------------------------------
//例子:forEach就是消费性函数接口
public class UnSafeList {
public static void main(String[] args) {
List<String> list = Arrays.asList("a", "b", "c");
list.forEach(System.out::println);
}
}
//forEach源码
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
供给型接口,没有输入参数,只有返回参数
public static void main(String[] args) {
Supplier<String> supplier=new Supplier<String>(){
@Override
public String get(){
return null;
}
};
Supplier<String> supplier = ()->{return "abc";};
System.out.println(supplier.get());
}
函数型接口,有一个输入,有一个输出
public static void main(String[]args){
// 函数式接口,可以改为 lambda 表达式
// Function<String,Integer> function = new Function<String, Integer>() {
// @Override
// public Integer apply(String s) {
// return 1024;
// }
// };
// 简写
Function<String, Integer> function=s->{return s.length();};
System.out.println(function.apply("abc"));
}
断定型接口,有一个输入参数,返回只有布尔值。
public static void main(String[] args) {
Predicate<String> predicate=new Predicate<String>(){
@Override
public boolean test(String s){
return false;
}
};
// 简写
Predicate<String> predicate = s -> {return s.isEmpty();};
System.out.println(predicate.test("abc"));
}
Stream流式计算:
流(Stream)到底是什么呢?
是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。“ 集合讲的是数据,流讲的是计算特点:Stream 自己不会存储元素。Stream 不会改变源对象,相反,他们会返回一个持有结果的新 Stream 。Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
测试代码
User
实体类
public class User {
private int id;
private String userName;
private int age;
//get、set、有参/无参构造器、toString
}
Stream应用
/*
* 题目:请按照给出数据,找出同时满足以下条件的用户
* 也即以下条件:
* 1、全部满足偶数ID
* 2、年龄大于24
* 3、用户名转为大写
* 4、用户名字母倒排序
* 5、只输出一个用户名字 limit
**/
public class StreamDemo {
public static void main(String[] args) {
User u1 = new User(11, "a", 23);
User u2 = new User(12, "b", 24);
User u3 = new User(13, "c", 22);
User u4 = new User(14, "d", 28);
User u5 = new User(16, "e", 26);
List<User> list = Arrays.asList(u1, u2, u3, u4, u5);
/*
* 1. 首先我们需要将 list 转化为stream流
* 2. 然后将用户过滤出来,这里用到一个函数式接口Predicate<? super T>,我们可
以使用lambda表达式简化
* 3. 这里面传递的参数,就是Stream流的泛型类型,也就是User,所以,这里可以直接
返回用户id为偶数的用户信息;
* 4. 通过forEach进行遍历,直接简化输出 System.out::println ,等价于
System.out.println(u);
**/
//1
//list.stream().filter(u -> {return u.getId() % 2 == 0;}).forEach(System.out::println);
//2
//list.stream().filter(u -> {return u.getId()%2==0;}).filter(u -> {return u.getAge()>24;}).forEach(System.out::println);
//sorted() 自然排序,正排序 D->E
list.stream()
.filter(u -> {
return u.getId() % 2 == 0;
})
.filter(u -> {
return u.getAge() > 24;
})
.map(u -> {
return u.getUserName().toUpperCase();
})
//.sorted() //默认正排序 自己用 compareTo 比较
.sorted((o1, o2) -> {
return o2.compareTo(o1);
})
.limit(1)
.forEach(System.out::println);
//map解释
List<Integer> list2 = Arrays.asList(1, 2, 3);
list2 = list2.stream().map(x -> {
return x * 2;
}).collect(Collectors.toList());
for (Integer element : list2) {
System.out.println(element);
}
}
}
特别注意 排序:
升序
自然排序
list = list.stream().sorted().collect(Collectors.toList());
定制排序
根据年龄升序排序。
list = list.stream().sorted(Comparator.comparing(Student::getAge)).collect(Collectors.toList());
降序
自然排序
使用Comparator 提供的reverseOrder() 方法
list = list.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
定制排序
根据年龄降序排序。
list = list.stream().sorted(Comparator.comparing(Student::getAge).reversed()).collect(Collectors.toList());
多字段排序
先按姓名升序,姓名相同则按年龄升序。
list = list.sorted(Comparator.comparing(Student::getName).thenComparing(Student::getAge)).collect(Collectors.toList());
异步回调
简介
Future
的优点:比更底层的
Thread
更易用。
要使用
Future
,通常只需要将耗时的操作封装在一个
Callable
对象中,再将它提交给
ExecutorService
。
为了让程序更加高效,让
CPU
最大效率的工作,我们会采用异步编程。首先想到的是开启一个新的线程去做某项工作。再进一步,为了让新线程可以返回一个值,告诉主线程事情做完了,于是乎Future
粉墨登场。然而Future
提供的方式是主线程主动问询新线程,要是有个回调函数就爽了。所以,为了满足Future的某些遗憾,强大的
CompletableFuture
随着
Java8
一起来了。
实例 没有返回值runAsync /有返回值supplyAsync
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
public class CompletableFutureDemo {
public static void main(String[] args) throws Exception {
//没有返回值的 runAsync 异步调用
CompletableFuture<Void> completableFuture =
CompletableFuture.runAsync(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "没有返回,update mysql ok");
});
System.out.println("111111"); // 先执行
completableFuture.get();
//有返回值的 供给型参数接口
CompletableFuture<Integer> completableFuture2 =
CompletableFuture.supplyAsync(() -> {
System.out.println(Thread.currentThread().getName() +
"completableFuture2");
int i = 10 / 0;
return 1024;
});
System.out.println(completableFuture2.whenComplete((t, u) -> { //编译完成,正常结束输出
System.out.println("===t:" + t); //正常结果
System.out.println("===u:" + u); //报错的信息
}).exceptionally(e -> { //结果异常,非正常结束
System.out.println("=======exception:" + e.getMessage());
return 555;
}).get());
}
}