一、流的操作流程
- 一个执行查询的数据源
- 一个中间操作链,形成一条流的流水线
- 一个终端操作,执行流水线,并能生成结果
@Data @Accessor(chain=true) //链式 public class User { private String id; private String name; private int age; public boolean isOldEnough(){ return age > 26; } } //生成数据源 public class UserUtils { public static List<User> createUsers(){ List<User> users = new ArrayList<User>(); for(int i = 0 ; i<100 ; i++){ User user = new User(); user.setId(i+"id").setName("name"+i).setAge(i); users .add(user); } return users; } }
二、中间操作的方法
1.用谓词筛选:filter(),该操作返回一个谓词做参数,并返回一个符合谓词的元素的流
//筛选出年龄大于26的用户 //老式写法 List<User> users = UserUtils.createUsers(); List<User> filteredUsers = new ArrayList<>(); users.forEach((user)->{ if(user.isOldEnough()){ filteredUsers .add(user); } }); //流式写法 List<User> users = UserUtils.createUsers().stream().filter(User :: isOldEnough).collect(Collectors.toList());
2.去重:distinct(),返回一个元素各异的流
List<User> users = UserUtils.createUsers().stream().distinct().(Collectors.toList());
3.截短流:limit(int n),返回一个指定长度的流
List<User> users = UserUtils.createUsers().stream().limit(6).(Collectors.toList());
4.跳过元素:skip(int n),返回一个丢弃了前n个元素的流,如果元素不足n个,则返回一个空流
List<User> users = UserUtils.createUsers().stream().skip(6).(Collectors.toList()); //skip()和limit()是一对方法,可以结合使用达到对数据进行分段处理的目的 List<User> users = UserUtils.createUsers().stream().skip(6).limit(6).(Collectors.toList()); //获取第二个6元素的集合
5.映射:map(),接收一个函数,将应用到每个元素上,并映射成一个新的元素
List<String> userNames = UserUtils.createUsers().stream().map(User :: getName).(Collectors.toList());
6.流的扁平化:flatMap(),各个数组并不是分别映射成一个流,而是转化为流的内容
List<Integer> num1 = Arrays.asList(1,2,3); List<Integer> num2 = Arrays.asList(3,4); List<int[]> list = num1.stream().flatMap(i->{ num2.stream().map(j->new int[]{i,j}) }).collect(Collectors.toList()); //执行结果为[(1,3),(1,4),(2,3),(2,4),(3,3),(3,4)]
三、终端操作的方法
1.查找和匹配:allMatch(),anyMatch(),noneMatch(),findFirst()和findAny()
boolean isOld = UserUtils.createUsers().stream().anyMatch(User :: isOldEnough); /** * allMatch(),检查是否所有的元素都符合给定的谓词 * anyMatch(),检查是否有一个元素符合给定的谓词 * noneMatch(),检查是否元素都不符合给定的谓词 * findAny(),返回当前流中的任意元素,可以和filter()结合使用效果更好 * findFirst(),查找第一个元素 */ List<User> users = UserUtils.createUsers().stream().filter(User :: isOldEnough).findAny();
规约:reduce(),将流中的元素反复结合起来,得到一个值
List<Integer> nums = Arrays.asList(1,2,3,4,5,6); int num = nums.stream().reduce(0,Integer :: sum); //执行结果21
收集器:collector(),将元素按指定方法收集起来
Collectors.toList(),把流中的所有元素收集到一个List里; .toSet(),返回一个set .toCollection(),把流中的所有元素放到指定的集合中 //使用方法:collect(toCollection(),ArrayList :: new); counting(),计算流中的元素个数; summingInt(),对流中的整数性求和; averaingInt(),返回平均值; summarizingInt(),收集流中的Integer属性的统计值,最大、最小、平均值等; joining(),调用toString()方法; maxBy(),按照指定比较器的最大值; minBy(),最小值; reducing(),合并为单个值(二进制); collectingAndThen(),对结果应用转换函数; groupingBy(),分组操作; partitingBy(boolean flag),对结果进行分区
并行流
parallel(),将顺序流变成并行流; sequential(),将并行流转换成顺序流;
list.parallelStream().sorted(Comparator.compring(User :: getName)).sequential().collect(Collectors.groupingB