天天看點

【Java8新特性】面試官:談談Java8中的Stream API有哪些終止操作?

Stream的終止操作

終端操作會從流的流水線生成結果。其結果可以是任何不是流的值,例如: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的每個終止方法。

1.allMatch()

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。

2.anyMatch()方法

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。

3.noneMatch()方法

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。

4.findFirst()方法

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());      

5.findAny()方法

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());      

6.count()方法

count()方法表示傳回流中元素總數。其在Stream接口中的定義如下所示。

long count();      

我們可以通過類似如下示例來使用count()方法。

long count = employees.stream().count();
System.out.println(count);      

7.max()方法

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());      

8.min()方法

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());      

9.forEach()方法

forEach()方法表示内部疊代(使用 Collection 接口需要使用者去做疊代,稱為外部疊代。相反, Stream API 使用内部疊代)。其在Stream接口内部的定義如下所示。

void forEach(Consumer<? super T> action);      

我們可以通過類似如下示例來使用forEach()方法。

employees.stream().forEach(System.out::println);      

規約

Stream API中有關規約的方法如下表所示。

【Java8新特性】面試官:談談Java8中的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());      

注意:上述例子使用了寫死的方式來累加某個具體值,大家在實際工作中再優化代碼。

收集

【Java8新特性】面試官:談談Java8中的Stream API有哪些終止操作?

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());      

如何收集Stream流?

Collector接口中方法的實作決定了如何對流執行收集操作(如收集到 List、 Set、 Map)。Collectors實用類提供了很多靜态方法,可以友善地建立常見收集器執行個體, 具體方法與執行個體如下表:

【Java8新特性】面試官:談談Java8中的Stream API有哪些終止操作?

每個方法對應的使用示例如下表所示。

【Java8新特性】面試官:談談Java8中的Stream API有哪些終止操作?
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());