相关文章推荐
迷茫的小笼包  ·  【转载】 ...·  2 周前    · 
寂寞的茄子  ·  java ...·  1 年前    · 

java8 stream流操作

概念:

Steam 是Java8 提出的一个新概念,不是输入输出的 Stream 流,而是一种用函数式编程方式在集合类上进行复杂操作的工具。简而言之,是以内部迭代的方式处理集合数据的操作,内部迭代可以将更多的控制权交给集合类。Stream 和 Iterator 的功能类似,只是 Iterator 是以外部迭代的形式处理集合数据的操作。

在Java8以前,对集合的操作需要写出处理的过程,如在集合中筛选出满足条件的数据,需要一 一遍历集合中的每个元素,再把每个元素逐一判断是否满足条件,最后将满足条件的元素保存返回。而Stream 对集合筛选的操作提供了一种更为便捷的操作,只需将实现函数接口的筛选条件作为参数传递进来,Stream会自行操作并将合适的元素同样以stream 的方式返回,最后进行接收即可。


中间操作

流中间操作在应用到流上,返回一个新的流。下面列出了常用的流中间操作:

  • map:通过一个 Function 把一个元素类型为 T 的流转换成元素类型为 R 的流。
  • flatMap:通过一个 Function 把一个元素类型为 T 的流中的每个元素转换成一个元素类型为 R 的流,再把这些转换之后的流合并。
  • filter:过滤流中的元素,只保留满足由 Predicate 所指定的条件的元素。
  • distinct:使用 equals 方法来删除流中的重复元素。
  • limit:截断流使其最多只包含指定数量的元素。
  • skip:返回一个新的流,并跳过原始流中的前 N 个元素。
  • sorted:对流进行排序。
  • peek:返回的流与原始流相同。当原始流中的元素被消费时,会首先调用 peek 方法中指定的 Consumer 实现对元素进行处理。
  • dropWhile:从原始流起始位置开始删除满足指定 Predicate 的元素,直到遇到第一个不满足 Predicate 的元素。
  • takeWhile:从原始流起始位置开始保留满足指定 Predicate 的元素,直到遇到第一个不满足 Predicate 的元素。

终结操作

终结操作产生最终的结果。

  • forEach 和 forEachOrdered 对流中的每个元素执行由 Consumer 给定的实现。在使用 forEach 时,并没有确定的处理元素的顺序;forEachOrdered 则按照流的相遇顺序来处理元素,如果流有确定的相遇顺序的话。
  • reduce进行递归计算
  • collect生成新的数据结构

Map

将一种类型的值映射为另一种类型的值,可以将 Stream 中的每个值都映射为一个新的值,最终转换为一个新的 Stream 流。

public class MapStreamTest {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("aa","bb","cc");
        //这里str -> str.toUpperCase()即为Function接口中apply方法的实现,所以其作用就是转为大写。
        list.stream().map(str -> str.toUpperCase()).forEach(System.out::println);
	//这个同上,是lambda的简写
        list.stream().map(String::toUpperCase).forEach(System.out::println);
}

Filter

遍历并筛选出满足条件的元素形成一个新的 Stream 流。

public class FilterStreamTest {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("java", "zhi", "hu", "javascript");
        //筛选已j开头的字符串的个数
	long count = list.stream().filter(p -> p.startsWith("j")).count();
	System.out.println(count);
}

flatMap

可用 Stream 替换值,并将多个 Stream 流合并成一个 Stream 流。

public class FlatMapStreamTest {
    public static void main(String[] args) {
       List<Integer> list = Stream.of(Arrays.asList(1, 2, 3, 4, 5, 6), Arrays.asList(8, 9, 10, 11, 12)).flatMap(test -> test.stream()).collect(Collectors.toList());
}

reduce(终止操作)

从 Stream 的一组值中生成另一个值。可以理解为递归。

public class ReduceStreamTest {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9);
        //这里0是初始值,第一次执行规约应该是0+1,其中1是第一个值  x是累计结果值,y是当前值
        Integer sum = list.stream().reduce(0, (x,y) -> x + y);
        System.out.println("sum:"+sum);
}

他就是一个不断 累计运算 的过程

stream.collect()方法

    <R, A> R collect(Collector<? super T, A, R> collector);
    <R> R collect(Supplier<R> supplier,
                  BiConsumer<R, ? super T> accumulator,
                  BiConsumer<R, R> combiner);

第1个方法,我们主要是使用 Collectors来进行各种 reduction 操作

  • Collectors.toSet() : 转换成set集合。
  • Collectors.toMap(x -> x, x -> x + 1) : 转换成map。
  • Collectors.minBy(Integer::compare) : 求最小值,相对应的当然也有maxBy。
  • Collectors.joining("-") : 拼接字符串。
  • 。。。(一系列方法)
public class CollectTest {
    public static void main(String[] args) {
       //将数组转为集合List
       String[] arr ={"aa","ccc","sss"};
       System.out.println(Arrays.stream(arr).collect(toList()));
       //将list中的数据分组 并统计数量
       List<Person> list = Arrays.asList(person1,person2,person3);
       Map<Integer, Long> personGroups = list.stream().collect(Collectors.groupingBy(Person::getAge,counting()));
}

第2个方法

  • Supplier 生产者, 返回最终结果
  • BiConsumer<R, ? super T> accumulator 累加器
  • 第一个参数是要返回的集合, 第二个参数是遍历过程中的每个元素,将流中每个被遍历的元素添加到集合中
  • BiConsumer<R, R> combiner 合并器, 在有并行流的时候才会有用, 一个流时代码不会走到这里
  • 将第二步遍历得到的所有流形成的list都添加到最终的list中
public class CollectTest {
    public static void main(String[] args) {
       Stream<String> stream = Stream.of("hello", "world", "helloworld");
       List<String> list = stream.collect(LinkedList::new, LinkedList::add, LinkedList::addAll);
}

Optional

具有以下两个特点:

  • 判断是否为null
  • 简化if else代码
public final class Optional<T> {
    private static final Optional<?> EMPTY = new Optional<>();
    private final T value;
    private Optional() {
        this.value = null;
    //创建一个空的 Optional 实例
    public static<T> Optional<T> empty() {
        @SuppressWarnings("unchecked")
        Optional<T> t = (Optional<T>) EMPTY;
        return t;
    private Optional(T value) {
        this.value = Objects.requireNonNull(value);
    //创建一个 Optional 实例,当 t为null时抛出异常
    public static <T> Optional<T> of(T value) {
        return new Optional<>(value);
    //创建一个 Optional 实例,但当 t为null时不会抛出异常,而是返回一个空的实例
    public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    //获取optional实例中的对象,当optional 容器为空时报错
    public T get() {
        if (value == null) {
            throw new NoSuchElementException("No value present");
        return value;
    //判断optional是否为空,如果空则返回false,否则返回true
    public boolean isPresent() {
        return value != null;
    //如果optional不为空,则将optional中的对象传给Comsumer函数
    public void ifPresent(Consumer<? super T> consumer) {
        if (value != null)
            consumer.accept(value);
    //如果optional不为空,则执行断言函数p,如果p的结果为true,则返回原本的optional,否则返回空的optional  
    public Optional<T> filter(Predicate<? super T> predicate) {
        Objects.requireNonNull(predicate);
        if (!isPresent())
            return this;
            return predicate.test(value) ? this : empty();
    //如果optional不为空,则将optional中的对象 t 映射成另外一个对象 u,并将 u 存放到一个新的optional容器中。
    public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return Optional.ofNullable(mapper.apply(value));
    //同上,在optional不为空的情况下,将对象t映射成另外一个optional。
    //区别:map会自动将u放到optional中,而flatMap则需要手动给u创建一个optional
    public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return Objects.requireNonNull(mapper.apply(value));
    // //如果optional不为空,则返回optional中的对象;如果为null,则返回 other 这个默认值
    public T orElse(T other) {
        return value != null ? value : other;
    //如果optional不为空,则返回optional中的对象;如果为null,则使用Supplier函数生成默认值other
    public T orElseGet(Supplier<? extends T> other) {
        return value != null ? value : other.get();
    //如果optional不为空,则返回optional中的对象;如果为null,则抛出Supplier函数生成的异常
    public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
        if (value != null) {
            return value;
        } else {
            throw exceptionSupplier.get();
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        if (!(obj instanceof Optional)) {
            return false;
        Optional<?> other = (Optional<?>) obj;
        return Objects.equals(value, other.value);
    @Override
    public int hashCode() {
        return Objects.hashCode(value);
    @Override
    public String toString() {
        return value != null
            ? String.format("Optional[%s]", value)
            : "Optional.empty";
}

demo

public class OptionalTest {
    public static void main(String[] args) {
        Person p1 = new Person();
        p1.debit = new Debit();
        p1.debit.card = new Card();
        p1.debit.card.bank = new Bank();
        p1.debit.card.bank.name = "ICBC";
        Person p2 = new Person();
	p2.debit = new Debit();
	p2.debit.card = new Card();
	Person p3 = new Person();
	p3.debit = new Debit();
	p3.debit.card = new Card();
	p3.debit.card.bank = new Bank();
	Person p4 = new Person();
	p4.debit = new Debit();
	p4.debit.card = new Card();
	p4.debit.card.bank = new Bank();
	p4.debit.card.bank.name = "ZSBC";
	Person p5 = new Person();
        //普通方法取值 VS Optional
        List<Person> list = Arrays.asList(p1,p2,p3,p4, p5);
	list.stream().map(OptionalExample::getDebitBankName_1).forEach(System.out::println);
	System.out.println("");
	list.stream().map(OptionalExample::getDebitBankName_2).forEach(System.out::println);
	System.out.println("");
    public static String getDebitBankName_1(Person person) {
	if (person.getDebit()!=null) {
		Debit debit = person.getDebit();
		if (debit!=null) {
			Card card = debit.getCard();
			if (card != null) {
				Bank bank = card.getBank();
				if (bank != null) {
				    return bank.getName();
		return null;
	}else {
		return null;
    public static String getDebitBankName_2(Person person) {
	return Optional.ofNullable(person.getDebit())