Java8之Stream

Posted weiqihome

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java8之Stream相关的知识,希望对你有一定的参考价值。

Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。

Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。

Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。

什么是 Stream?

Stream(流)是一个来自数据源的元素队列并支持聚合操作:

  • 元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算
  • 数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。
  • 聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。

和以前的Collection操作不同, Stream操作还有两个基础的特征:

  • Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。
  • 内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。

流的创建

  • stream() − 为集合创建串行流。
  • parallelStream() − 为集合创建并行流。parallelStream其实就是一个并行执行的流.它通过默认的ForkJoinPool,可能提高你的多线程任务的速度。并行流在遍历时可能是无序的。
public class StreamTest 
    public static void main(String[] args) 
        //通过Arrays.stream创建流
        int[] intarr = 1,2,3,4,5,6;
        Arrays.stream(intarr).forEach(System.out::println);
        //通过Stream.of创建流
        Stream.of("a","b","c").forEach(System.out::println);
        //通过Collection的stream方法创建流
        List<String> list = Arrays.asList("a","b","c");
        list.stream().forEach(System.out::println);
        //通过Stream.iterate方法创建流(不断循环创建出无限流)
        Stream.iterate(1,i->i+1).limit(5).forEach(System.out::println);
        //通过Stream.generate创建流(不断循环创建无限流)
        Stream.generate(()->1).limit(5).forEach(System.out::println);
    

常用方法forEach、map、filter、limit、sorted、collect

forEach用来对stream中的数据进行迭代,传入一个Consumer参数:

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

//Consumer
@FunctionalInterface
public interface Consumer<T> 
    void accept(T t);

    default Consumer<T> andThen(Consumer<? super T> after) 
        Objects.requireNonNull(after);
        return (T t) ->  accept(t); after.accept(t); ;
    


//例:以下两种方式效果相同,下面一种为lambda方法推导方式,写法更为简洁
//forEach方法传入一个Consumer接口实现类,流中的所有数据都依次执行Consumer中的accept方法
 Stream.of("a","b","c").forEach((str)-> System.out.println(str)); 
 Stream.of("a","b","c").forEach(System.out::println); 

filter 方法用于通过设置的条件过滤出元素

Stream<T> filter(Predicate<? super T> predicate);

//Predicate
@FunctionalInterface
public interface Predicate<T> 

    boolean test(T t);

    default Predicate<T> negate() 
        return (t) -> !test(t);
    

    default Predicate<T> or(Predicate<? super T> other) 
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    

    static <T> Predicate<T> isEqual(Object targetRef) 
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    


//filter中传入一个Predicate接口实现类//将流中等于"a"的字符串过滤出来
Stream.of("a","b","c").filter((str)>str.equals("a")).forEach(System.out::println);

map 方法用于映射每个元素到对应的结果,可以将提取集合类中某一个类型:

<R> Stream<R> map(Function<? super T, ? extends R> mapper);

//Function apply方法:传入参数类型T,返回结果类型R
@FunctionalInterface
public interface Function<T, R> 

    R apply(T t);

    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) 
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    

    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) 
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    

    static <T> Function<T, T> identity() 
        return t -> t;
    


//Apple类中有int类型weight和String类型color,提取出List<Apple>中的所有weight
class Apple
    private int weight;
    private String color;

    public Apple(int weight, String color) 
        this.weight = weight;
        this.color = color;
    
    //省略getter、setter、toString


public class Java8T1 
    public static void main(String[] args) 
        List<Apple> list = new ArrayList<>();
        for (int i=0;i<10;i++)
            list.add(new Apple(i,"color"+i));
        
        System.out.println(list);
        List<Integer> collect = list.stream().map((apple -> apple.getWeight())).collect(Collectors.toList());
        System.out.println(collect);
    


//打印如下:
[Appleweight=0, color=‘color0‘, Appleweight=1, color=‘color1‘, Appleweight=2, color=‘color2‘, Appleweight=3, color=‘color3‘, Appleweight=4, color=‘color4‘, Appleweight=5, color=‘color5‘, Appleweight=6, color=‘color6‘, Appleweight=7, color=‘color7‘, Appleweight=8, color=‘color8‘, Appleweight=9, color=‘color9‘]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

limit 方法用于获取指定数量的流:

Stream<T> limit(long maxSize);

//传入一个long类型数字,获取前面多少个数据
Stream.of("a","b","c").limit(2).forEach(System.out::print);

sorted 方法用于对流进行排序:

Stream<T> sorted();
Stream<T> sorted(Comparator<? super T> comparator);

//无参数方法使用默认排序方法,有参数排序自定义排序规则
Stream.of(1,2,3,4,5).sorted().forEach(System.out::print);
System.out.println();
Stream.of(1,2,3,4,5).sorted((a,b)->b-a).forEach(System.out::print);

//打印如下
12345
54321

collect用于返回新的数据结构,在map方法中使用到了collect返回一个新的int类型List

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

<R, A> R collect(Collector<? super T, A, R> collector);

//可以转为其他数据结构
Set<Integer> set = Stream.of(1, 2, 3, 4, 5).collect(Collectors.toSet());
List<Integer> list = Stream.of(1, 2, 3, 4, 5).collect(Collectors.toList());

 

以上是关于Java8之Stream的主要内容,如果未能解决你的问题,请参考以下文章

Java8学习笔记--Stream API详解[转]

java8stream学习笔记

Java 8 中的 Streams API 详解

java代码之美---Java8 Stream

jdk8中的stream

Java 8 中的 Streams API 详解