Java8 02 Stream

1、概念

Stream API提供了一种高效的且易于使用的处理数据方法
Stream(流),是数据渠道,用于操作数据源(集合、数组等)所产生的元素序列
所以流代表了计算

注意:
⑴ Stream自己不会存储元素
⑵ Stream不会改变源对象,会返回一个新的带有结果的Stream
⑶ Stream操作是延迟执行的,也就是会等到需要结果的时候才会执行

2、Stream的操作

⑴ 创建Stream

通过集合或数组来获取一个流

⒈ Arrays的stream方法

public static <T> Stream<T> stream(T[] array) {
    return stream(array, 0, array.length);
}

⒉ Collection接口的stream方法

default Stream<E> stream() {
  return StreamSupport.stream(spliterator(), false);
}

default Stream<E> parallelStream() {
   return StreamSupport.stream(spliterator(), true);
}

获取一个串行流

⒊ Stream的of方法

public static<T> Stream<T> of(T... values) {
    return Arrays.stream(values);
}

传递一个数组

public static<T> Stream<T> of(T t) {
    return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
}

传递一个对象

⒋ Stream的iterate方法

public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) {}

创建一个无限流,第一个参数是种子数,第二个参数是函数式接口
种子数即要生成的元素的起始元素
函数式接口则定义了元素生成的策略

⒌ Stream的generate方法

public static<T> Stream<T> generate(Supplier<T> s) {}

创建一个无限流,需要提供一个供给型函数

⒍ 示例

  String[] array = {"a", "b", "c", "d"};
  List<Integer> list = new ArrayList<Integer>() {
      {
          add(1);
          add(2);
          add(3);
          add(4);
      }
  };

   Stream<String> streamArray = Arrays.stream(array);
   Stream<Integer> streamList = list.stream(); // 串行流
   streamList = list.parallelStream(); // 并行流
   Stream<Double> stream = Stream.of(1D, 2D, 3D, 4D);
   stream = Stream.of(10D);


    Stream<Integer> stream = Stream.iterate(1, (x) -> {return ++x;}); // 无限流
    stream.limit(10)
          .forEach(System.out::println);
    stream.close(); // 关闭流


    Stream<Integer> stream = Stream.generate(() -> {return (int) (Math.random() * 10 + 1);}); // 创建1-10的随机数
    stream.limit(10)
          .forEach(System.out::println);
    stream.close();

⑵ 中间操作

一个中间操作链,对数据源的数据进行操作

⒈ 筛选和切片

filter

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

筛选,需要传递一个断言型接口

distinct

Stream<T> distinct();

去重。注意:这里会调用元素的hashCode和equals方法

limit

Stream<T> limit(long maxSize);

取出前几个元素。如果元素个数不够,则有几个就返回几个

skip

Stream<T> skip(long n);

跳过前几个元素。如果跳过后,元素的个数为0,则返回一个包含了空元素的Stream

示例
【bean对象】
public class Person {
    private String name;
    private Integer age;
    private Double salary;
    /** Constructor & Getter & Setter */
}

    List<Person> list = new ArrayList<Person>() {
        {
            add(new Person("张三", 14, 2000.15D));
            add(new Person("李四", 16, 3010.5D));
            add(new Person("王五", 13, 2600.43D));
            add(new Person("赵六", 11, 2800.43D));
            add(new Person("王五", 13, 2600.43D));
            add(new Person("田七", 14, 2758.54D));
        }
    };

    list.stream()
            .filter((person) -> {return 12 < person.getAge();}) // 筛选年龄大于12岁的
            .distinct() // 去重
            .skip(1) // 跳过第一个元素
            .limit(3) // 取出前3个元素
            .forEach(System.out::println);

⒉ 映射

map

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

映射规则,需要传递一个供给型函数

示例

    List<Person> list = Arrays.asList(
            new Person("张三", 14, 2000.15D),
            new Person("李四", 16, 3010.5D),
            new Person("王五", 13, 2600.43D),
            new Person("赵六", 11, 2800.43D),
            new Person("王五", 13, 2600.43D),
            new Person("田七", 14, 2758.54D)
    );
    List<String> names = list.stream()
                             .map(Person::getName)
                             .collect(Collectors.toList());
    names.forEach(System.out::println);

mapToDouble

DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper);

示例

  OptionalDouble optionalDouble = list.stream().mapToDouble(Person::getSalary).max();
  System.out.println(optionalDouble.getAsDouble());

mapToInt

mapToLong

flatMap

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

传递一个函数型的接口,返回值类型为一个Stream流

示例

    List<String> names = Arrays.asList("ada", "bob", "cad", "dgb");
    names.stream()
         .flatMap(类名::mapper) // 静态方法引用
         .sorted() // 自然排序
         .forEach(System.out::print);

【需要自定义一个方法】
    private static Stream<Character> mapper(String str) {
        List<Character> temp = new ArrayList<Character>();

        char[] array = str.toCharArray();
        for (int i = 0, len = array.length; i < len; i++) {
            temp.add(array[i]);
        }

        return temp.stream();
    }

⒊ 排序

sorted

Stream<T> sorted();

自然排序

 public final Stream<P_OUT> sorted(Comparator<? super P_OUT> comparator) {}
    定制排序,需要传递一个Comparator比较器

示例

【自然排序】

    List<Integer> list = Arrays.asList(1, 2, 34, 5, 53, 5, 45, 35);
    list.stream()
        .sorted()
        .forEach(System.out::println);

【定制排序】

    list.stream()
        .sorted((x, y) -> {return -(x.compareTo(y));}) // 倒序
        .forEach(System.out::println);

⑶ 终止操作

Stream流水线的最终生成结果,其结果可能不是Stream,可能是集合,也可能是void

⒈ 查找与匹配

allMatch

boolean allMatch(Predicate<? super T> predicate);

全部元素匹配,需要传递一个断言型函数

示例

    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
    boolean flag = list.stream()
                       .allMatch((i) -> {return 10 > i;});
    System.out.println(flag);
anyMatch
    boolean anyMatch(Predicate<? super T> predicate);

任意元素匹配,需要传递一个断言型函数

示例

    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
    boolean flag = list.stream()
                       .anyMatch((i) -> {return 5 >= i;});
    System.out.println(flag);
noneMatch
   boolean noneMatch(Predicate<? super T> predicate);

没有元素匹配,需要传递一个断言型函数

示例

    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
    boolean flag = list.stream()
                        .noneMatch((i) -> {return 5 < i;});
    System.out.println(flag);
findFirst
    Optional<T> findFirst();

取出第一个元素,并将元素封装到Optional对象中,返回

示例

    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
    Optional<Integer> optional = list.stream()
                                     .findFirst();
    System.out.println(optional.get());
findAny
    Optional<T> findAny();

取出任意一个元素(符合条件的第一个),并将元素封装到Optional对象中,返回

示例

    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
    Optional<Integer> optional = list.stream()
                                     .filter((x) -> {return 4 < x;}) // 过滤大于4的元素
                                     .findAny(); // 等同于取出第一个大于4的元素
    System.out.println(optional.get());
count
long count();

返回Stream中包含的元素的个数

示例

    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
    long count = list.stream()
                     .count();
    System.out.println(count);
max
Optional<T> max(Comparator<? super T> comparator);

示例

    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
    Optional<Integer> max = list.stream()
                                .max(Integer::compareTo); // 实例方法引用
    System.out.println(max.get());
min
   Optional<T> min(Comparator<? super T> comparator);

示例

    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
    Optional<Integer> max = list.stream()
                                .min(Integer::compareTo);
    System.out.println(max.get());
forEach
    void forEach(Consumer<? super T> action);

内部遍历,需要传递一个消费型接口

示例

    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
    list.stream()
        .forEach(System.out::println);

⒉ 规约

reduce

 T reduce(T identity, BinaryOperator<T> accumulator);
  第一个参数传递结果的起始值,第二个参数需要传递一个BiFunction<T,T,T>类型的函数式接口。返回第一个参数类型的返回值

interface BinaryOperator<T> extends BiFunction<T,T,T> {}

Optional<T> reduce(BinaryOperator<T> accumulator);
  需要传递一个BiFunction<T,T,T>类型的函数式接口,将结果封装到Optional中并返回

示例

    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
    Optional<Integer> optional = list.stream()
                                     .reduce(Integer::sum);
    System.out.println(optional.get());

    Integer sum = list.stream()
                      .reduce(0, (x, y) -> {return x + y;}); // 结果的起始值为0
    System.out.println(sum);

⒊ 收集

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

需要传递Collector的实现类Collectors

toList
public static <T> Collector<T, ?, List<T>> toList() {}

将流中的元素收集到List集合(ArrayList)中

toSet
public static <T> Collector<T, ?, Set<T>> toSet() {}

将流中的元素收集到Set集合(HashSet)中

toCollection
public static <T, C extends Collection<T>>
Collector<T, ?, C> toCollection(Supplier<C> collectionFactory) {}

把流中的元素收集到Collection集合中。需要传递集合的类型,可以使用构造引用

示例

    List<Integer> list = Arrays.asList(1, 3, 2, 3, 5, 4, 5);
    Collection<Integer> collection = list.stream()
                                         .collect(Collectors.toCollection(LinkedList::new)); // 创建的集合类型为LinkedList
    System.out.println(collection);
counting
public static <T> Collector<T, ?, Long> counting() {}

统计元素个数,返回值类型为Long

示例

    List<Integer> list = Arrays.asList(1, 3, 2, 3, 5, 4, 5);
    Long count = list.stream()
                     .collect(Collectors.counting());
    System.out.println(count); // 7
summingInt
public static <T> Collector<T, ?, Integer>
summingInt(ToIntFunction<? super T> mapper) {}

对元素的整数属性进行合计。需要传递ToIntFunction类型的函数式接口,该函数用以定义如何合计元素的值

示例

    List<Person> persons = new ArrayList<Person>(3);
    persons.add(new Person(12));
    persons.add(new Person(13));
    persons.add(new Person(15));
    Integer sum = persons.stream()
                         .collect(Collectors.summingInt(Person::getAge)); // 实例方法引用
    System.out.println(sum);
averagingInt
 public static <T> Collector<T, ?, Double>
averagingInt(ToIntFunction<? super T> mapper) {}

计算Integer元素的平均值。需要传递ToIntFunction类型的函数式接口

示例:

    List<Person> persons = new ArrayList<Person>(3);
    persons.add(new Person(12));
    persons.add(new Person(13));
    persons.add(new Person(15));
    Double avgAge = persons.stream()
                           .collect(Collectors.averagingInt(Person::getAge));
    System.out.println(avgAge);
summarizingInt
public static <T>
Collector<T, ?, IntSummaryStatistics> summarizingInt(ToIntFunction<? super T> mapper) {}

获取处理指定元素类型的收集器

IntSummaryStatistics类的方法:
double getAverage()
long getCount()
int getMax()
int getMin()
long getSum()

示例:

    List<Person> persons = new ArrayList<Person>(3);
    persons.add(new Person(12));
    persons.add(new Person(13));
    persons.add(new Person(15));
    IntSummaryStatistics intSummaryStatistics = persons.stream().collect(Collectors.summarizingInt(Person::getAge));
    double avg = intSummaryStatistics.getAverage(); // 平均值
    long count = intSummaryStatistics.getCount(); // 统计个数
    int max = intSummaryStatistics.getMax(); // 最大值
    int min = intSummaryStatistics.getMin(); // 最小值
    long sum = intSummaryStatistics.getSum(); // 合计
    System.out.println(avg);
    System.out.println(count);
    System.out.println(max);
    System.out.println(min);
    System.out.println(sum);
joining
  public static Collector<CharSequence, ?, String> joining() {}

拼接元素为字符串

public static Collector<CharSequence, ?, String> joining(CharSequence delimiter) {}

传递分割符号

public static Collector<CharSequence, ?, String> joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix) {}

传递分割符号,前缀和后缀

示例:

    List<Person> persons = new ArrayList<Person>(3);
    persons.add(new Person("张三"));
    persons.add(new Person("李四"));
    persons.add(new Person("王五"));
    String result = persons.stream()
                           .map(Person::getName)
                           .collect(Collectors.joining());
    System.out.println(result);

    result = persons.stream()
                    .map(Person::getName)
                    .collect(Collectors.joining(", "));
    System.out.println(result);

    result = persons.stream()
                    .map(Person::getName)
                    .collect(Collectors.joining(",", "[", "]"));
    System.out.println(result);
maxBy
public static <T> Collector<T, ?, Optional<T>>
maxBy(Comparator<? super T> comparator) {}

根据比较器选择最大值

示例:

    List<Person> persons = new ArrayList<Person>(3);
    persons.add(new Person("ada",14));
    persons.add(new Person("bob", 12));
    persons.add(new Person("cad",15));
    Optional<Integer> optional = persons.stream()
                                        .map(Person::getAge)
                                        .collect(Collectors.maxBy(Integer::compareTo));
    System.out.println(optional.get());
minBy
  根据比较器选择最小值
reducing
  public static <T> Collector<T, ?, T>
    reducing(T identity, BinaryOperator<T> op) {}

从一个指定的值开始,将各个元素按照指定的规则计算到一起

示例:

    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
    Integer sum = list.stream()
                      .collect(Collectors.reducing(0, Integer::sum));
    System.out.println(sum);
groupingBy
public static <T, K> Collector<T, ?, Map<K, List<T>>>
groupingBy(Function<? super T, ? extends K> classifier) {}
按照指定的属性对元素进行分组操作,返回Map<属性,List<对应属性值的集合>>

示例:

    List<Person> list = Arrays.asList(
            new Person(13),
            new Person(23),
            new Person(23),
            new Person(14)
    );
    Map<Integer, List<Person>> map = list.stream()
                                         .collect(Collectors.groupingBy(Person::getAge));
    map.forEach((k, v) -> {System.out.println(k + "-" + v);});
partitioningBy
public static <T>
Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate) {}

按照true | false进行分区

示例:

    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    Map<Boolean, List<Integer>> collect = numbers.stream()
                                                 .collect(Collectors.partitioningBy((i) -> {return 3 < i;}));
    collect.forEach((k, v) -> {System.out.println(k + ":" + v);});

3、Fork/Join框架

⑴ 概念

    将一个大任务拆分(fork)成多个小任务,知道不能再拆分为止(达到临界值),然后再将一个一个小任务的结果汇总(join)起来

⑵ 与线程池的区别

    Fork/Join采用工作窃取模式(work-stealing),即当执行新任务时,会把任务拆分成更小的任务去执行,再将小任务添加到线程队列中,然后再随机从一个线程队列中偷取一个小任务,并把它放到自己的线程队列中
    Fork/Join的优势体现在对任务的处理方式上
    一般的线程池,如果其中一个线程的执行任务无法继续进行,则该线程会处于等待状态
    而在Fork/Join框架中,由于该线程处于空闲状态,所以它会偷取其他线程队列上的尚未被执行的子任务,并处理,以此提高了效率

⑶ API

编写一个类,并继承RecursiveTask抽象类,并实现compute方法

public final ForkJoinTask fork() {}
拆分任务

public final V join() {}
合并任务

⑷ 示例

/**
 * 求和
 */
public class TestForkJoin extends RecursiveTask<Long> {
    private static final long THRESHOLD = 1000L;
    private long start;
    private long end;

    public TestForkJoin(long start, long end) {
        this.start = start;
        this.end = end;
    }

    @Override
    protected Long compute() {
        long length = end - start; // 计算出间距
        if (THRESHOLD >= length) {
            long sum = 0L;
            for (long i = start; i <= end; i++) {
                sum += i;
            }
            return sum;
        } else {
            long middle = (start + end) / 2; // 求出临界值
            TestForkJoin left = new TestForkJoin(start, middle);
            left.fork(); // 拆分任务,添加到线程队列中
            TestForkJoin right = new TestForkJoin(middle + 1, end); // 从中间部分加1开始计算
            right.fork();
            return left.join() + right.join(); // 合并子任务的结果
        }
    }

}

4、并行流和串行流

⑴ 概念

并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流(Stream)

⑵ API

IntStream
LongStream
DoubleStream

S parallel();
获取并行流

S sequential();
获取串行流

public static IntStream rangeClosed(int startInclusive, int endInclusive) {
    if (startInclusive > endInclusive) {
        return empty();

}
获取从开始到结束的自增结果,每次自增1
类似于:

for (int i = startInclusive; i <= endInclusive ; i++) { ... }

注意:如果第一个参数(开始位置)大于第二个参数(结束位置),则返回空的Stream

public static LongStream rangeClosed(long startInclusive, final long endInclusive) {
    if (startInclusive > endInclusive) {
        return empty();

}

获取从开始到结束的自增结果,每次自增1
类似于:

for (long i = startInclusive; i <= endInclusive ; i++) { ... }

注意:如果第一个参数(开始位置)大于第二个参数(结束位置),则返回空的Stream

注意:DoubleStream没有rangeClosed方法

⑶ 示例

    long sum = LongStream.rangeClosed(1L, 100000000L)
                         .sequential()
                         .sum();
    System.out.println(sum);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值