文章目录
JAVA8新特性之Stream API
Java8中有两大最为重要的改变。第一个是 Lambda 表达式;另外一个则是 Stream API。Stream API ( java.util.stream) 把真正的函数式编程风格引入到Java中。这是目前为止对Java类库最好的补充,因为Stream API可以极大提供Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询
为什么要使用Stream API?
实际开发中,项目中多数数据源都来自于Mysql,Oracle等。但现在数据源可以更多了,有MongDB,Radis等,而这些NoSQL的数据就需要Java层面去处理。
Stream 和 Collection 集合的区别:Collection 是一种静态的内存数据结构,而 Stream 是有关计算的。前者是主要面向内存,存储在内存中,后者主要是面向 CPU,通过 CPU 实现计算。
Stream是什么?
Stream是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。“集合讲的是数据,Stream讲的是计算!”
- Stream 自己不会存储元素。
- Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
- Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
Stream的创建
String[] array = {"花木兰","马超","元歌"};
List<String> list = Arrays.asList(array);
Stream<String> stream1 = Arrays.stream(array);//使用java.util.Arrays.stream(T[] array)方法用数组创建流
Stream<String> stream2 = list.stream();//java.util.Collection.stream() 方法用集合创建流
Stream<String> stream3 = Stream.of("东方镜","东方曜");//使用Stream的静态方法:of()
遍历/匹配(foreach/find/match)
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7,8,9,10);
list.stream().filter(x -> x>5 ).forEach(System.out::println);//6,7,8,9,10
Optional<Integer> first = list.stream().findFirst();//根据命名可以大致知道是获取Optional流中的第一个元素。
System.out.println(first.get());//1
Optional<Integer> any = list.stream().findAny();//1
System.out.println(any.get());//获取Optional 流中任意一个,存在随机性,其实里面也是获取元素中的第一个。
boolean anyMatch = list.stream().anyMatch(x -> x > 6);
System.out.println(anyMatch);//true
聚合(max/min/count)
List<String> nameList = Arrays.asList("elena", "jack", "tom", "anny");
Optional<String> max = nameList.stream().max(Comparator.comparing(String::length));
Optional<String> min = nameList.stream().min(Comparator.comparing(String::length));
System.out.println(nameList.stream().count());//几个人 4
System.out.println(min.get());//最短短名字 tom
System.out.println(max.get());//最长的名字 elena
List<Integer> numlist = Arrays.asList(1, 2, 3, 4, 5, 6, 7,8,9,10);
Optional<Integer> maxNum = numlist.stream().max(Integer::compareTo);
Optional<Integer> minNum = numlist.stream().min(Integer::compareTo);
System.out.println(numlist.stream().count());//10
System.out.println(maxNum.get());//最大的数字 10
System.out.println(minNum.get());//最小的数字 1
映射(map/flatMap)
List<String> list = new ArrayList();
Collections.addAll(list,"elena","tom","jack");
Stream<String> stringStream1 = list.stream().map(String::toUpperCase);
stringStream1.forEach(System.out::println);// ELENA TOM JACK
归约(reduce)
List<Integer> list = Arrays.asList(1,2,3,4,5,6);
//求和
Optional<Integer> sum = list.stream().reduce((Integer::sum));
System.out.println(sum.get());
// 求乘积
Optional<Integer> product = list.stream().reduce((x, y) -> x * y);
System.out.println(product.get());
归集(toList/toSet/toMap)
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Emp {
/**
* 员工姓名
*/
private String ename;
/**
* 员工工资
*/
private Integer salary;
/**
* 员工年龄
*/
private Integer age;
/**
* 员工性别
*/
private String sex;
}
List<Emp> list = new ArrayList<>();
list.add(new Emp("elena", 5000, 23, "男"));
list.add(new Emp("jack", 6000, 25, "女"));
list.add(new Emp("tom", 7000, 21, "男"));
list.add(new Emp("anny", 8000, 24, "女"));
List<Emp> collect = list.stream().filter(item-> item.getSalary() > 6000).collect(Collectors.toList());
Set<Emp> set = list.stream().filter(item -> item.getSalary() > 6000).collect(Collectors.toSet());
Map<String, Emp> map = list.stream().filter(item -> item.getSalary() > 6000).collect(Collectors.toMap(Emp::getEname, p -> p));
collect.forEach(System.out::println);
set.forEach(System.out::println);
map.forEach((k,v)->{ System.out.println("k:"+k+" v:"+v); });
统计(count/averaging)
List<Emp> list = new ArrayList<>();
list.add(new Emp("elena", 5000, 23, "男"));
list.add(new Emp("jack", 6000, 25, "女"));
list.add(new Emp("tom", 7000, 21, "男"));
list.add(new Emp("anny", 8000, 24, "女"));
// 求总数
Long count = list.stream().collect(Collectors.counting());
// 求平均工资
Double average = list.stream().collect(Collectors.averagingDouble(Emp::getSalary));
// 求最高工资
Optional<Integer> max = list.stream().map(Emp::getSalary).collect(Collectors.maxBy(Integer::compare));
// 求工资之和
Integer sum = list.stream().collect(Collectors.summingInt(Emp::getSalary));
// 一次性统计所有信息
DoubleSummaryStatistics collect = list.stream().collect(Collectors.summarizingDouble(Emp::getSalary));
System.out.println("员工总数:" + count);
System.out.println("员工平均工资:" + average);
System.out.println("员工工资总和:" + sum);
System.out.println("员工工资所有统计:" + collect);
分组(partitioningBy/groupingBy)
List<Emp> list = new ArrayList<>();
list.add(new Emp("elena", 5000, 23, "男"));
list.add(new Emp("jack", 6000, 25, "女"));
list.add(new Emp("tom", 7000, 21, "男"));
list.add(new Emp("anny", 8000, 24, "女"));
//按工资分为两个Map,员工按薪资是否高于6000分。
Map<Boolean, List<Emp>> collect = list.stream().collect(Collectors.partitioningBy(x -> x.getSalary() > 6000));
//按照性别
Map<String, List<Emp>> collect1 = list.stream().collect(Collectors.groupingBy(Emp::getSex));
//按照性别和年龄
Map<String, Map<Integer, List<Emp>>> collect2 = list.stream().collect(Collectors.groupingBy(Emp::getSex, Collectors.groupingBy(Emp::getAge)));
System.out.println(collect);
System.out.println(collect1);
System.out.println(collect2);
接合(joining)
List<String> list = Arrays.asList("A", "B", "C");
String string = list.stream().collect(Collectors.joining(","));
System.out.println(string);//A,B,C
排序(sorted)
List<Emp> list = new ArrayList<>();
list.add(new Emp("jack", 6000, 22, "女"));
list.add(new Emp("tom", 7000, 22, "男"));
list.add(new Emp("elena", 5000, 21, "男"));
list.add(new Emp("anny", 8000, 23, "女"));
//按年龄
List<Emp> collect1 = list.stream().sorted(Comparator.comparing(Emp::getAge)).collect(Collectors.toList());
//按年龄倒序排序
List<Emp> collect2 = list.stream().sorted(Comparator.comparing(Emp::getAge).reversed()).collect(Collectors.toList());
//先按年龄再按工资
List<Emp> collect3 = list.stream().sorted(Comparator.comparing(Emp::getAge).thenComparing(Emp::getSalary)).collect(Collectors.toList());
//自定义排序 按工资
List<Emp> collect4 = list.stream().sorted((o1, o2) -> o2.getSalary() - o1.getSalary()).collect(Collectors.toList());
提取/组合
List<String> strings = Arrays.asList("1", "2", "3", "3", "4", "5");
List<String> strings2 = Arrays.asList("6", "7", "8", "9", "10");
//去重
List<String> collect = strings.stream().distinct().collect(Collectors.toList());
System.out.println(collect);//[1, 2, 3, 4, 5]
//合并
List<String> collect1 = Stream.concat(strings.stream(), strings2.stream()).collect(Collectors.toList());
System.out.println(collect1);//[1, 2, 3, 4, 5]
//取多少条
List<String> collect2 = collect1.stream().limit(2).collect(Collectors.toList());
System.out.println(collect2);//[1, 2]
//跳过前n条
List<String> collect3 = collect1.stream().skip(2).collect(Collectors.toList());
System.out.println(collect3);//[3, 3, 4, 5, 6, 7, 8, 9, 10]