作者个人研发的在高并发场景下,提供的简单、稳定、可扩展的延迟消息队列框架,具有精准的定时任务和延迟队列处理功能。自开源半年多以来,已成功为十几家中小型企业提供了精准定时调度方案,经受住了生产环境的考验。为使更多童鞋受益,现给出开源框架地址:
https://github.com/sunshinelyz/mykit-delay
PS: 欢迎各位Star源码,也可以pr你牛逼哄哄的代码。
如果你出去面试,面试官问了你关于Java8 Stream API的一些问题,比如:Java8中创建Stream流有哪几种方式?(可以参见:《【Java8新特性】面试官问我:Java8中创建Stream流有哪几种方式?》)Java8中的Stream API有哪些中间操作?(可以参见:《【Java8新特性】Stream API有哪些中间操作?看完你也可以吊打面试官!!》)如果你都很好的回答了这些问题,那么,面试官可能又会问你:Java8中的Stream API有哪些终止操作呢?没错,这就是Java8中有关Stream API的灵魂三问!不要觉得是面试官在为难你,只有你掌握了这些细节,你就可以反过来吊打面试官了!
终端操作会从流的流水线生成结果。其结果可以是任何不是流的值,例如:List、 Integer、Double、String等等,甚至是 void 。
在Java8中,Stream的终止操作可以分为:查找与匹配、规约和收集。接下来,我们就分别简单说明下这些终止操作。
Stream API中有关查找与匹配的方法如下表所示。
同样的,我们对每个重要的方法进行简单的示例说明,这里,我们首先建立一个Employee类,Employee类的定义如下所示。
@Data
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class Employee implements Serializable {
private static final long serialVersionUID = -9079722457749166858L;
private String name;
private Integer age;
private Double salary;
private Stauts stauts;
public enum Stauts{
WORKING,
SLEEPING,
VOCATION
}
}
接下来,我们在测试类中定义一个用于测试的集合employees,如下所示。
protected List<Employee> employees = Arrays.asList(
new Employee("张三", 18, 9999.99, Employee.Stauts.SLEEPING),
new Employee("李四", 38, 5555.55, Employee.Stauts.WORKING),
new Employee("王五", 60, 6666.66, Employee.Stauts.WORKING),
new Employee("赵六", 8, 7777.77, Employee.Stauts.SLEEPING),
new Employee("田七", 58, 3333.33, Employee.Stauts.VOCATION)
);
好了,准备工作就绪了。接下来,我们就开始测试Stream的每个终止方法。
allMatch()方法表示检查是否匹配所有元素。其在Stream接口中的定义如下所示。
boolean allMatch(Predicate<? super T> predicate);
我们可以通过类似如下示例来使用allMatch()方法。
boolean match = employees.stream().allMatch((e) -> Employee.Stauts.SLEEPING.equals(e.getStauts()));
System.out.println(match);
注意:使用allMatch()方法时,只有所有的元素都匹配条件时,allMatch()方法才会返回true。
anyMatch方法表示检查是否至少匹配一个元素。其在Stream接口中的定义如下所示。
boolean anyMatch(Predicate<? super T> predicate);
我们可以通过类似如下示例来使用anyMatch()方法。
boolean match = employees.stream().anyMatch((e) -> Employee.Stauts.SLEEPING.equals(e.getStauts()));
System.out.println(match);
注意:使用anyMatch()方法时,只要有任意一个元素符合条件,anyMatch()方法就会返回true。
noneMatch()方法表示检查是否没有匹配所有元素。其在Stream接口中的定义如下所示。
boolean noneMatch(Predicate<? super T> predicate);
我们可以通过类似如下示例来使用noneMatch()方法。
boolean match = employees.stream().noneMatch((e) -> Employee.Stauts.SLEEPING.equals(e.getStauts()));
System.out.println(match);
注意:使用noneMatch()方法时,只有所有的元素都不符合条件时,noneMatch()方法才会返回true。
findFirst()方法表示返回第一个元素。其在Stream接口中的定义如下所示。
Optional<T> findFirst();
我们可以通过类似如下示例来使用findFirst()方法。
Optional<Employee> op = employees.stream().sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())).findFirst();
System.out.println(op.get());
findAny()方法表示返回当前流中的任意元素。其在Stream接口中的定义如下所示。
Optional<T> findAny();
我们可以通过类似如下示例来使用findAny()方法。
Optional<Employee> op = employees.stream().filter((e) -> Employee.Stauts.WORKING.equals(e.getStauts())).findFirst();
System.out.println(op.get());
count()方法表示返回流中元素总数。其在Stream接口中的定义如下所示。
long count();
我们可以通过类似如下示例来使用count()方法。
long count = employees.stream().count();
System.out.println(count);
max()方法表示返回流中最大值。其在Stream接口中的定义如下所示。
Optional<T> max(Comparator<? super T> comparator);
我们可以通过类似如下示例来使用max()方法。
Optional<Employee> op = employees.stream().max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
System.out.println(op.get());
min()方法表示返回流中最小值。其在Stream接口中的定义如下所示。
Optional<T> min(Comparator<? super T> comparator);
我们可以通过类似如下示例来使用min()方法。
Optional<Double> op = employees.stream().map(Employee::getSalary).min(Double::compare);
System.out.println(op.get());
forEach()方法表示内部迭代(使用 Collection 接口需要用户去做迭代,称为外部迭代。相反, Stream API 使用内部迭代)。其在Stream接口内部的定义如下所示。
void forEach(Consumer<? super T> action);
我们可以通过类似如下示例来使用forEach()方法。
employees.stream().forEach(System.out::println);
Stream API中有关规约的方法如下表所示。
reduce()方法在Stream接口中的定义如下所示。
T reduce(T identity, BinaryOperator<T> accumulator);
Optional<T> reduce(BinaryOperator<T> accumulator);
<U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner);
我们可以通过类似如下示例来使用reduce方法。
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Integer sum = list.stream().reduce(0, (x, y) -> x + y);
System.out.println(sum);
System.out.println("----------------------------------------");
Optional<Double> op = employees.stream().map(Employee::getSalary).reduce(Double::sum);
System.out.println(op.get());
我们也可以搜索employees列表中“张”出现的次数。
Optional<Integer> sum = employees.stream()
.map(Employee::getName)
.flatMap(TestStreamAPI1::filterCharacter)
.map((ch) -> {
if(ch.equals('六'))
return 1;
else
return 0;
}).reduce(Integer::sum);
System.out.println(sum.get());
注意:上述例子使用了硬编码的方式来累加某个具体值,大家在实际工作中再优化代码。
collect()方法在Stream接口中的定义如下所示。
<R> R collect(Supplier<R> supplier,
BiConsumer<R, ? super T> accumulator,
BiConsumer<R, R> combiner);
<R, A> R collect(Collector<? super T, A, R> collector);
我们可以通过类似如下示例来使用collect方法。
Optional<Double> max = employees.stream()
.map(Employee::getSalary)
.collect(Collectors.maxBy(Double::compare));
System.out.println(max.get());
Optional<Employee> op = employees.stream()
.collect(Collectors.minBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
System.out.println(op.get());
Double sum = employees.stream().collect(Collectors.summingDouble(Employee::getSalary));
System.out.println(sum);
Double avg = employees.stream().collect(Collectors.averagingDouble(Employee::getSalary));
System.out.println(avg);
Long count = employees.stream().collect(Collectors.counting());
System.out.println(count);
System.out.println("--------------------------------------------");
DoubleSummaryStatistics dss = employees.stream()
.collect(Collectors.summarizingDouble(Employee::getSalary));
System.out.println(dss.getMax());
Collector接口中方法的实现决定了如何对流执行收集操作(如收集到 List、 Set、 Map)。Collectors实用类提供了很多静态方法,可以方便地创建常见收集器实例, 具体方法与实例如下表:
每个方法对应的使用示例如下表所示。
public void test4(){
Optional<Double> max = emps.stream()
.map(Employee::getSalary)
.collect(Collectors.maxBy(Double::compare));
System.out.println(max.get());
Optional<Employee> op = emps.stream()
.collect(Collectors.minBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
System.out.println(op.get());
Double sum = emps.stream()
.collect(Collectors.summingDouble(Employee::getSalary));
System.out.println(sum);
Double avg = emps.stream()
.collect(Collecors.averagingDouble(Employee::getSalary));
System.out.println(avg);
Long count = emps.stream()
.collect(Collectors.counting());
DoubleSummaryStatistics dss = emps.stream()
.collect(Collectors.summarizingDouble(Employee::getSalary));
System.out.println(dss.getMax());
如果觉得文章对你有点帮助,请微信搜索并关注「 冰河技术 」微信公众号,跟冰河学习Java8新特性。
最后,附上Java8新特性核心知识图,祝大家在学习Java8新特性时少走弯路。