1.Strem()流式处理
特点和特性
特性
- stream不存储数据,而是按照特定的规则对数据进行计算,一般会输出结果。
- stream不会改变数据源,通常情况下会产生一个新的集合或一个值。
- stream具有延迟执行特性,只有调用终端操作时,中间操作才会执行。
特点
- 代码简洁:函数编程写出的代码简洁且意图明确,使用stream接口让你从此告别for循环。
- 多核友好:Java函数式编程使得编写并行程序从未如此简单,你需要的全部就是调用一下方法。
- Stream不存储数据
- Stream不会改变源对象。相反,他们会返回一个持有结果的新Stream。
- Stream是惰性求值的(延迟执行)
创建Stream
//返回一个顺序流
Stream<String> stream = lists.stream();
//返回一个并行流
Stream<String> stream2 = lists.parallelStream();
中间操作
-
筛选切片
方法 描述 distinct() 筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素 limit(long maxSize) 载断流,使其元素不超过给定数量 skip(long n) 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补 filter(Predicate p) 接收 Lambda , 从流中排除某些元素 -
映射map
方法 描述 map(Function f) 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。 mapToDouble(ToDoubleFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的DoubleStream。 mapTolnt(TolntFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的IntStream。 mapToLong(ToLongFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的LongStream。 flatMap(Function f) 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流 -
排序
方法 描述 sorted() 产生一个新流,其中按自然顺序排序 sorted(Comparator com) 产生一个新流,其中按比较器顺序排序 终止操作
-
匹配与查找
方法 描述 allMatch(Predicate p) 检查是否匹配所有元素 anyMatch(Predicate p) 检查是否至少匹配一个元素 noneMatch(Predicate p) 检查是否没有匹配所有元素 findFirst() 返回第一个元素 findAny() 返回当前流中的任意元素 count() 返回流中元素总数 max(Comparator c) 返回流中最大值 min(Comparator c) 返回流中最小值 forEach(Consumer c) 内部迭代(使用Collection接口需要用户去做迭代,称为外部迭代)。相反,Stream API使用内部迭代—它帮你把迭代做了 -
归约
方法 描述 reduce(T iden,BinaryOperator b) 可以将流中元素反复结合起来,得到一个值。返回T reduce(BinaryOperator b) 可以将流中元素反复结合起来,得到一个值。返回Optional -
收集
方法 描述 collect(Collector) 将流转为其他形式。接收一个Collector接口的实现,用于给Stream中元素做汇总的方法
-
例子
1.根据某个属性过滤对象数组
class Student{
public Integer age;
public String name;
public String sex;
}
List<Student> students = new ArrayList<>();
List<Student> result = students.stream().filter(student -> student.getSex().equals("女")).collect(Collectors.toList());
2.分组
List<Order> orders = Lists.newArrayList();
// 按照订单类型分组
Map<String, List<Order>> orderGroupMap = orders.stream().collect(Collectors.groupingBy(Order::getType));
3.去重
List<Order> orders = Lists.newArrayList();
// 按照订单编号去重
orders = orders.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(()
-> new TreeSet<>(Comparator.comparing(Order::getNum))), ArrayList::new));
// 按照订单编号和类型去重
orders = orders.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(()
-> new TreeSet<>(Comparator.comparing(o -> o.getNum() + ";" + o.getType()))), ArrayList::new));
4.List转Map
List<Order> orders = Lists.newArrayList();
// 将订单集合转换成订单编号-应付金额 map,注意订单编号作为 key 不能重复,应先做去重处理
Map<String, Float> numPayMap = orders.stream().collect(Collectors.toMap(Order::getNum, Order::getPayAmt));
// 用 id 做 key 将 List 转成 Map
Map<Long, Order> orderMap = orders.stream().collect(Collectors.toMap(Order::getId, item -> item));
5.排序
List<Order> orders = Lists.newArrayList();
// 按照订单总金额从高到低排序
// 方式一
orders.sort((o1, o2)
-> o1.getAllAmt() == null ? 1 : (o2.getAllAmt() == null ? -1 : o2.getAllAmt().compareTo(o1.getAllAmt())));
// 方式二
orders.sort(Comparator.comparing(Order::getAllAmt, (o1, o2)
-> o1 == null ? 1 : (o2 == null ? -1 : o2.compareTo(o1))));
// 方式三 (allAmt 字段不能为 null, null 会导致排序失败)
orders.sort(Comparator.comparing(Order::getAllAmt).reversed());
// 先按照订单类型排序,再按照订单应付金额从高到低排序
orders.sort(Comparator.comparing(Order::getType, (o1, o2)
-> o1 == null ? 1 : (o2 == null ? -1 : o1.compareTo(o2))).thenComparing((o1, o2)
-> o1.getPayAmt() == null ? 1 : (o2.getPayAmt() == null ? -1 : o2.getPayAmt().compareTo(o1.getPayAmt()))));
6.统计计数
List<Order> orders = Lists.newArrayList();
// 统计所有订单的总金额
// 求和
Double sum = orders.stream().filter(item -> item.getAllAmt() != null).mapToDouble(Order::getAllAmt).sum();
// 最大总金额
OptionalDouble max = orders.stream().filter(item -> item.getAllAmt() != null).mapToDouble(Order::getAllAmt).max();
// 防止没有订单数据的处理
Double maxAllAmt = max.isPresent() ? max.getAsDouble() : 0;
// 最小总金额
OptionalDouble min = orders.stream().filter(item -> item.getAllAmt() != null).mapToDouble(Order::getAllAmt).min();
// 平均总金额
OptionalDouble average = orders.stream().filter(item -> item.getAllAmt() != null).mapToDouble(Order::getAllAmt).average();