Everyone should know the lambda expression of jdk8, it is still relatively easy to use, the usage is introduced below
Introduction to Lambda
Lambda expressions are a new feature of JDK8, which can replace most of the anonymous inner classes and write more elegant Java code, especially in the traversal of collections and other collection operations, which can greatly optimize the code structure.
JDK also provides a large number of built-in functional interfaces for us to use, making the use of Lambda expressions more convenient and efficient.
The grammatical form is () -> {}, where () is used to describe the parameter list, {} is used to describe the method body, and -> is the lambda operator, pronounced (goes to).
Streams
Stream has several characteristics:
- Stream does not store data, but calculates the data according to specific rules, and generally outputs the result.
- Stream does not change the data source, and usually generates a new set or a value.
- Stream has a delayed execution feature, and the intermediate operation will only be executed when the terminal operation is called.
(Use collect when gathering, and use map when operating on objects)
Match
stringList.sort((a,b)->a.compareTo(b)); //排序
boolean ret = stringList.stream().anyMatch(x->x.startsWith("a"));
match
anyMatch means that any element
in the judgment condition is successful and returns true. AllMatch means that all elements in the judgment condition are all true
. NoneMatch is the opposite of allMatch. If all elements in the judgment condition are not, it returns true.
Filter/count
long num = stringList.stream().filter(x->x.startsWith("b")).count();
List<Integer> list = Arrays.asList(3,2,67,9,1);
Integer i = list.stream().min(Integer::compareTo).get();
Sum
double total = accountList.stream().mapToDouble(Account::getBalance).sum();
Parallel Streams
Parallel stream is faster than serial stream, but you need to pay attention to whether there is data disorder in the usage scenario. So when to use parallelStream?
- Note whether the list elements can be processed in parallel?
- Are the elements independent?
- Is there a distinction between calling order?
- If there are none, you can use this stream more quickly
//对象TestDTO
Map<String, List<TestDTO>> sortAppId = list.parallelStream().collect(
Collectors.groupingBy(TestDTO::getAppId));
//appid为对象的一个属性
//可用大括号具体操作
list.parallelStream().map(x -> {
x.setOrderId(1);
return x;
}).collect(Collectors.toList());
asynchronous
public static void sync() throws Exception {
//异步执行
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
}
if(new Random().nextInt()%2>=0) {
int i = 12/0;
}
System.out.println("run end ...");
});
//异步完成回调
future.whenComplete(new BiConsumer<Void, Throwable>() {
@Override
public void accept(Void t, Throwable action) {
System.out.println("执行完成!");
}
});
//异步异常回调
future.exceptionally(new Function<Throwable, Void>() {
@Override
public Void apply(Throwable t) {
System.out.println("执行失败!"+t.getMessage());
return null;
}
});
TimeUnit.SECONDS.sleep(2);
}
Use of map
List<Employee> employees = initList();
List<Integer> employeeList = employees.stream().map(Employee::getId)
.collect(toList());
//提取为Map1
Map<Integer, Employee> idEmployeeMap = employees.stream().collect(
Collectors.toMap(Employee::getId, Function.identity()));
//提取为map2,value为List
Map<Integer, List<Employee>> departGroupMap = employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartId));
//提取为map3,value为list下对象中的一个字段的集合
Map<Integer, List<String>> departNamesMap =employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartId,
Collectors.mapping(Employee::getName, Collectors.toList()))
);
//获取一个属性的集合
List<String> workIds = list.parallelStream().map(TestDTO::getWorkId)
.collect(Collectors.toList());
/**
* List -> Map
* 需要注意的是:
* toMap 如果集合对象有重复的key,会报错Duplicate key ....
* apple1,apple12的id都为1。
* 可以用 (k1,k2)->k1 来设置,如果有重复的key,则保留key1,舍弃key2
*/
Map<Integer, Apple> appleMap = appleList.stream().collect(
Collectors.toMap(Apple::getId, a -> a,(k1,k2)->k1));
max use
Optional<Person> max = personList.stream()
.max(Comparator.comparingInt(Person::getSalary));
stream reduction
Multiple in one
public class StreamTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 3, 2, 8, 11, 4);
// 求和方式1
Optional<Integer> sum = list.stream().reduce((x, y) -> x + y);
// 求和方式2
Optional<Integer> sum2 = list.stream().reduce(Integer::sum);
// 求和方式3
Integer sum3 = list.stream().reduce(0, Integer::sum);
// 求乘积
Optional<Integer> product = list.stream().reduce((x, y) -> x * y);
// 求最大值方式1
Optional<Integer> max = list.stream().reduce((x, y) -> x > y ? x : y);
// 求最大值写法2
Integer max2 = list.stream().reduce(1, Integer::max);
System.out.println("list求和:" + sum.get() + "," + sum2.get() + "," + sum3);
System.out.println("list求积:" + product.get());
System.out.println("list求和:" + max.get() + "," + max2);
}
}
// 求工资之和方式1:
Optional<Integer> sumSalary = personList.stream().map(Person::getSalary)
.reduce(Integer::sum);
// 求工资之和
Integer sum = personList.stream()
.collect(Collectors.summingInt(Person::getSalary));
// 求最高工资方式1:
Integer maxSalary = personList.stream()
.reduce(0, (max, p) -> max > p.getSalary() ? max : p.getSalary(),
Integer::max);
// 求最高工资
Optional<Integer> max = personList.stream().map(Person::getSalary)
.collect(Collectors.maxBy(Integer::compare));
Collectors
Collectors provides a series of static methods for data statistics:
Count: count
平均值:averagingInt、averagingLong、averagingDouble
Maximum value: maxBy, minBy
Sum: summingInt, summingLong, summingDouble
Count all the above: summarizingInt, summarizingLong, summarizingDouble
// 求平均工资
Double average = personList.stream()
.collect(Collectors.averagingDouble(Person::getSalary));
// 一次性统计所有信息
DoubleSummaryStatistics collect = personList.stream()
.collect(Collectors.summarizingDouble(Person::getSalary));
返回
DoubleSummaryStatistics{count=3, sum=23700.000000,min=7000.000000, average=7900.000000, max=8900.000000}
Grouping
将员工按薪资是否高于8000分组
Map<Boolean, List<Person>> part = personList.stream().collect(Collectors.partitioningBy(x -> x.getSalary() > 8000));
// 将员工按性别分组
Map<String, List<Person>> group = personList.stream().collect(Collectors.groupingBy(Person::getSex));
// 将员工先按性别分组,再按地区分组
Map<String, Map<String, List<Person>>> group2 = personList.stream().collect(Collectors.
groupingBy(Person::getSex, Collectors.groupingBy(Person::getArea)));
Joining
//用逗号给集合中的名字连接起来
String names = personList.stream().map(p -> p.getName()).collect(Collectors.joining(","));
Collectors' reduction
Compared with the reduce method of stream itself, support for custom reduction is added.
Sorted
There are two sorts:
- sorted(): Natural sorting, the elements in the stream need to implement the Comparable interface
- sorted (Comparator com): Comparator sorter custom sorting
stringList.stream().map(String::toUpperCase).sorted((a,b)->a.compareTo(b)).forEach(System.out::println);
// 按工资增序排序
List<String> newList = personList.stream().sorted(Comparator.comparing(Person::getSalary)).map(Person::getName)
.collect(Collectors.toList());
// 按工资倒序排序
List<String> newList2 = personList.stream().sorted(Comparator.comparing(Person::getSalary).reversed())
.map(Person::getName).collect(Collectors.toList());
De-duplication
stream().map(YxStoreProduct::getProductServerId).distinct().collect(Collectors.toList());
Reference: https://mp.weixin.qq.com/s/WM4IfFcEilY3dGTfa2ap9g