Java8-04-03-笔记

Stream终止操作

  • 终止操作(终端操作)会从流的流水线生成结果,其结果可以是任何不是流的值。例如:List、Integer,甚至是void。

1,查找与匹配

allMatch(Predicate p) —— 检查是否匹配所有元素
anyMatch(Predicate p) —— 检查是否至少匹配一个元素
noneMatch(Predicate p) —— 检查是否所有元素都没有匹配

findFirst() —— 返回第一个元素
findAny() —— 返回当前流中的任意元素

count() —— 返回流中元素总数
max(Comparator c) —— 返回流中最大值
min(Comparator c) —— 返回流中最小值
forEach(Consumer c) —— 内部迭代(使用Collection接口需要用户去做的迭代称为外部迭代,
								相反,Stream API使用内部迭代——它帮你把迭代做了)
  • 案例演示
package com.sunstone.stream;

import com.sunstone.lambda.Employee;
import org.junit.Test;

import java.util.*;
import java.util.stream.Stream;

public class TestStream {

    List<Employee> emps = Arrays.asList(
            new Employee("小孙", 17, 5555.55),
            new Employee("小思", 27, 3333.33),
            new Employee("小东", 37, 9999.99),
            new Employee("小零", 50, 7777.77),
            new Employee("小雪", 7, 8888.88),
            new Employee("小豹", 60, 6666.66)
    );

    @Test
    public void test8() {
        boolean b1 = emps.stream().allMatch((e) -> e.getName().equals("小东"));//false
        boolean b2 = emps.stream().anyMatch((e) -> e.getName().equals("小东"));//true
        boolean b3 = emps.stream().noneMatch((e) -> e.getName().equals("stone"));//true

        Optional<Employee> op1 = emps.stream()
                .sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))
                .findFirst();
        System.out.println(op1.get());

        Optional<Employee> op2 = emps.stream()
                .filter((e) -> e.getAge() > 25)
                .findAny();
        System.out.println(op2.get());
        Optional<Employee> op3 = emps.parallelStream()
                .filter((e) -> e.getAge() > 25)
                .findAny();
        System.out.println(op3.get());
    }

    @Test
    public void test9() {
        Long count=emps.stream().count();
        System.out.println(count);

        Optional<Employee> op1=emps.stream().max((e1, e2)->Double.compare(e1.getSalary(),e2.getSalary()));
        System.out.println(op1.get());//薪水最高员工

        Optional<Double> op2 =emps.stream().map(Employee::getSalary).min(Double::compare);
        System.out.println(op2.get());//最低薪水
    }
}

2,归约

reduce(T identity, BinaryOperator b) —— 可以将流中元素反复结合起来,得到一个值。返回T类型值
reduce(BinaryOperator b) —— 可以将流中元素反复结合起来,得到一个值。返回Optional<T>

public interface BinaryOperator<T> extends BiFunction<T,T,T>抽象方法就是BiFunction中的apply
public interface BiFunction<T, U, R> {
    R apply(T t, U u);
    ...}
备注:map和reduce的连接通常称为map-reduce模式,因为Google用它来进行网络搜索而出名。
  • 案例演示
package com.sunstone.stream;

import com.sunstone.lambda.Employee;
import org.junit.Test;

import java.util.*;
import java.util.stream.Stream;

public class TestStream {

    List<Employee> emps = Arrays.asList(
            new Employee("小孙", 17, 5555.55),
            new Employee("小思", 27, 3333.33),
            new Employee("小东", 37, 9999.99),
            new Employee("小零", 50, 7777.77),
            new Employee("小雪", 7, 8888.88),
            new Employee("小豹", 60, 6666.66)
    );

    @Test
    public static void test10() {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
        Integer sum = list.stream().reduce(0, (x, y) -> x + y); //第一次 x=0,y=1->1
                                                                //第二次 x=1,y=2->3
                                                                //第三次 x=3,y=3->6  ...
        System.out.println(sum);//28

        Optional<Double> op = emps.stream()
                                    .map(Employee::getSalary)
                                    .reduce(Double::sum);//sum是Double的静态方法
                                            //可能第1个Employee元素getSalary为空
                                            //无法有初值 结果为空所以返回Optional
                                            //Optional的具体用法会在之后进行讨论
        System.out.println(op.get());
    }
}

3,收集

collect(Collector c) —— 将流转换为其他形式。接收一个Collector接口的实现,用于给Stream中元素做汇总的方法
Collector(接口)中方法的实现决定了如何对流执行收集操作(如收集到List、Set、Map)
同时Collectors(实现类)提供了很多的静态方法,可以方便地创建常见收集器实例
package java.util.stream;
//...
/*
Since:	1.8
See Also:	IntStream, LongStream, DoubleStream, java.util.stream
Type parameters:	<T> – the type of the stream elements
*/
public interface Stream<T> extends BaseStream<T, Stream<T>> {

    /**
     * Performs a <a href="package-summary.html#MutableReduction">mutable
     * reduction</a> operation on the elements of this stream using a
     * {@code Collector}.  A {@code Collector}
     * encapsulates the functions used as arguments to
     * {@link #collect(Supplier, BiConsumer, BiConsumer)}, allowing for reuse of
     * collection strategies and composition of collect operations such as
     * multiple-level grouping or partitioning.
     *
     * <p>If the stream is parallel, and the {@code Collector}
     * is {@link Collector.Characteristics#CONCURRENT concurrent}, and
     * either the stream is unordered or the collector is
     * {@link Collector.Characteristics#UNORDERED unordered},
     * then a concurrent reduction will be performed (see {@link Collector} for
     * details on concurrent reduction.)
     *
     * <p>This is a <a href="package-summary.html#StreamOps">terminal
     * operation</a>.
     *
     * <p>When executed in parallel, multiple intermediate results may be
     * instantiated, populated, and merged so as to maintain isolation of
     * mutable data structures.  Therefore, even when executed in parallel
     * with non-thread-safe data structures (such as {@code ArrayList}), no
     * additional synchronization is needed for a parallel reduction.
     *
     * @apiNote
     * The following will accumulate strings into an ArrayList:
     * <pre>{@code
     *     List<String> asList = stringStream.collect(Collectors.toList());
     * }</pre>
     *
     * <p>The following will classify {@code Person} objects by city:
     * <pre>{@code
     *     Map<String, List<Person>> peopleByCity
     *         = personStream.collect(Collectors.groupingBy(Person::getCity));
     * }</pre>
     *
     * <p>The following will classify {@code Person} objects by state and city,
     * cascading two {@code Collector}s together:
     * <pre>{@code
     *     Map<String, Map<String, List<Person>>> peopleByStateAndCity
     *         = personStream.collect(Collectors.groupingBy(Person::getState,
     *                                                      Collectors.groupingBy(Person::getCity)));
     * }</pre>
     *
     * @param <R> the type of the result
     * @param <A> the intermediate accumulation type of the {@code Collector}
     * @param collector the {@code Collector} describing the reduction
     * @return the result of the reduction
     * @see #collect(Supplier, BiConsumer, BiConsumer)
     * @see Collectors
     */
    <R, A> R collect(Collector<? super T, A, R> collector);
    ...
}
package java.util.stream;
//...

/**
 * Implementations of {@link Collector} that implement various useful reduction
 * operations, such as accumulating elements into collections, summarizing
 * elements according to various criteria, etc.
 *
 * <p>The following are examples of using the predefined collectors to perform
 * common mutable reduction tasks:
 *
 * <pre>{@code
 *     // Accumulate names into a List
 *     List<String> list = people.stream().map(Person::getName).collect(Collectors.toList());
 *
 *     // Accumulate names into a TreeSet
 *     Set<String> set = people.stream().map(Person::getName).collect(Collectors.toCollection(TreeSet::new));
 *
 *     // Convert elements to strings and concatenate them, separated by commas
 *     String joined = things.stream()
 *                           .map(Object::toString)
 *                           .collect(Collectors.joining(", "));
 *
 *     // Compute sum of salaries of employee
 *     int total = employees.stream()
 *                          .collect(Collectors.summingInt(Employee::getSalary)));
 *
 *     // Group employees by department
 *     Map<Department, List<Employee>> byDept
 *         = employees.stream()
 *                    .collect(Collectors.groupingBy(Employee::getDepartment));
 *
 *     // Compute sum of salaries by department
 *     Map<Department, Integer> totalByDept
 *         = employees.stream()
 *                    .collect(Collectors.groupingBy(Employee::getDepartment,
 *                                                   Collectors.summingInt(Employee::getSalary)));
 *
 *     // Partition students into passing and failing
 *     Map<Boolean, List<Student>> passingFailing =
 *         students.stream()
 *                 .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));
 *
 * }</pre>
 *
 * @since 1.8
 */
public final class Collectors {
		...
}
  • 案例演示
package com.sunstone.stream;

import com.sunstone.lambda.Employee;
import org.junit.Test;

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class TestStream {

    List<Employee> emps = Arrays.asList(
            new Employee("小孙", 17, 5555.55),
            new Employee("小思", 27, 3333.33),
            new Employee("小东", 37, 9999.99),
            new Employee("小零", 50, 7777.77),
            new Employee("小雪", 7, 8888.88),
            new Employee("小豹", 60, 6666.66)
    );

    @Test//收集到集合
    public void test11() {
        List<String> list = emps.stream().map(Employee::getName).collect(Collectors.toList());
        list.forEach(System.out::println);//Collectors.toList() 把流中元素收集到List
        Set<String> set = emps.stream().map(Employee::getName).collect(Collectors.toSet());
        set.forEach(System.out::println);//Collectors.toSet() 把流中元素收集到Set
        HashSet<String> hs=emps.stream().map(Employee::getName).collect(Collectors.toCollection(HashSet::new));
        hs.forEach(System.out::println);//Collectors.toCollection(Supplier<C> collectionFactory)把流中的元素收集到创建的集合中
    }
}
package com.sunstone.stream;

import com.sunstone.lambda.Employee;
import org.junit.Test;

import java.util.*;
import java.util.stream.Collectors;

public class TestStream {

    List<Employee> emps = Arrays.asList(
            new Employee("小孙", 17, 5555.55),
            new Employee("小思", 27, 3333.33),
            new Employee("小东", 37, 9999.99),
            new Employee("小零", 50, 7777.77),
            new Employee("小雪", 7, 8888.88),
            new Employee("小豹", 60, 6666.66)
    );

    @Test
    public void test12(){//统计值
        Long count=emps.stream().collect(Collectors.counting());//总数
        Double avg=emps.stream().collect(Collectors.averagingDouble(Employee::getSalary));//平均值
        Double sum=emps.stream().collect(Collectors.summingDouble(Employee::getSalary));//总和
		//上面的这几个方法和下面的获取最大最小值进行对比
		//下面的能够明显看出map映射到薪资,再在collect中使用minBy获取的是薪资最小值
		//				如果处在employee集合的流,在collect中使用maxBy获取的则是集合元素中比较的最大值
		//但是上面的函数本想既然是计算薪资的统计值,是不是先map到薪资的流,再使用collect,试了下,并不可以#@——@#
		
        Optional<Employee> maxEmp =emps.stream()
                .collect(Collectors.maxBy((e1,e2)->Double.compare(e1.getSalary(), e2.getSalary())));
        System.out.println(maxEmp.get());//最大薪资员工
        Optional<Double> minSalary =emps.stream()
                .map(Employee::getSalary).collect(Collectors.minBy(Double::compareTo));
        System.out.println(minSalary.get());//最小薪资
    }
}
package com.sunstone.stream;

import com.sunstone.lambda.Employee;
import com.sunstone.lambda.Status;
import org.junit.Test;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class TestStream {

    List<Employee> emps = Arrays.asList(
            new Employee("小孙", 17, 5555.55, Status.XIANDEYAOMING),//Employee新增Status状态属性
            new Employee("小思", 27, 3333.33, Status.XIANDEYAOMING),
            new Employee("小东", 37, 9999.99, Status.XIANDEYAOMING),
            new Employee("小零", 50, 7777.77, Status.BUSY),
            new Employee("小雪", 7, 8888.88, Status.HOLIDAY),
            new Employee("小豹", 60, 6666.66, Status.HOLIDAY)
    );

    @Test
    public void test13() {//分组、分区
        Map<Status, List<Employee>> map1 = emps.stream().collect(Collectors.groupingBy(Employee::getStatus));//分组
        System.out.println(map1);                                                   //根据某个属性的值对流进行分组,属性为key

        Map<Status, Map<String, List<Employee>>> map2 = emps.stream()
                .collect(Collectors.groupingBy(Employee::getStatus,Collectors.groupingBy(((e)->{//多级分组
                    if(e.getAge()<=35){
                        return "青年";
                    }else if(e.getAge()<50){
                        return "中年";
                    }else{
                        return "老年";
                    }
                }))));
        System.out.println(map2);

        Map<Boolean,List<Employee>> map3 = emps.stream().collect(Collectors.partitioningBy((e)->e.getSalary()>8000));//分区
        System.out.println(map3);                                                   //根据true和false分组,key为boolean值
    }
}
/*
输出结果,分别为:
{HOLIDAY=[Employee{name='小雪', age=7, salary=8888.88, status=HOLIDAY}, Employee{name='小豹', age=60, salary=6666.66, status=HOLIDAY}], BUSY=[Employee{name='小零', age=50, salary=7777.77, status=BUSY}], XIANDEYAOMING=[Employee{name='小孙', age=17, salary=5555.55, status=XIANDEYAOMING}, Employee{name='小思', age=27, salary=3333.33, status=XIANDEYAOMING}, Employee{name='小东', age=37, salary=9999.99, status=XIANDEYAOMING}]}
{HOLIDAY={青年=[Employee{name='小雪', age=7, salary=8888.88, status=HOLIDAY}], 老年=[Employee{name='小豹', age=60, salary=6666.66, status=HOLIDAY}]}, BUSY={老年=[Employee{name='小零', age=50, salary=7777.77, status=BUSY}]}, XIANDEYAOMING={青年=[Employee{name='小孙', age=17, salary=5555.55, status=XIANDEYAOMING}, Employee{name='小思', age=27, salary=3333.33, status=XIANDEYAOMING}], 中年=[Employee{name='小东', age=37, salary=9999.99, status=XIANDEYAOMING}]}}
{false=[Employee{name='小孙', age=17, salary=5555.55, status=XIANDEYAOMING}, Employee{name='小思', age=27, salary=3333.33, status=XIANDEYAOMING}, Employee{name='小零', age=50, salary=7777.77, status=BUSY}, Employee{name='小豹', age=60, salary=6666.66, status=HOLIDAY}], true=[Employee{name='小东', age=37, salary=9999.99, status=XIANDEYAOMING}, Employee{name='小雪', age=7, salary=8888.88, status=HOLIDAY}]}
*/
package com.sunstone.stream;

import com.sunstone.lambda.Employee;
import com.sunstone.lambda.Status;
import org.junit.Test;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class TestStream {

    List<Employee> emps = Arrays.asList(
            new Employee("小孙", 17, 5555.55, Status.XIANDEYAOMING),//Employee新增Status状态属性
            new Employee("小思", 27, 3333.33, Status.XIANDEYAOMING),
            new Employee("小东", 37, 9999.99, Status.XIANDEYAOMING),
            new Employee("小零", 50, 7777.77, Status.BUSY),
            new Employee("小雪", 7, 8888.88, Status.HOLIDAY),
            new Employee("小豹", 60, 6666.66, Status.HOLIDAY)
    );

    @Test
    public void test14() {

        DoubleSummaryStatistics dss =emps.stream()
                .collect(Collectors.summarizingDouble(Employee::getSalary));//收集流中属性的统计值
        System.out.println(dss.getSum()+" "+ dss.getAverage()+" "+ dss.getCount()+" "+dss.getMax()+" "+dss.getMin());//根据情况获取值

        String str =emps.stream().map(Employee::getName)
                .collect(Collectors.joining(",","==","---"));//字符串连接
        System.out.println(str);
    }
}
/*
输出结果,分别为:
42222.18 7037.03 6 9999.99 3333.33
==小孙,小思,小东,小零,小雪,小豹---
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值