流产生的背景

集合是 Java 中使用最多的 API,但在 Java 中,集合操作却不像 SQL 语句那样简洁明了;想要用并行架构处理大量集合元素,也很困难。


为了解决这个问题,Java 8 API 中添加了新的成员 - 流(Stream)。

它允许以声明性方式(即通过类似查询语句来表达,而不是编写一个实现类)来处理数据集合;还可以不写任何多线程代码进行透明地并行处理。


流的作用与特点 

作用:从支持数据处理操作的源,生成的元素序列。

特点:

  • 流水线:很多流操作本身会返回一个流,这样多个操作就可以链接起来,形成一个大的流水线

  • 内部迭代:与使用迭代器显式迭代的集合不同,流的迭代操作是在背后进行的

  • 和迭代器类似,流只能遍历一次

 

Stream 接口的使用

Java 8 中的 java.util.Collection 接口,支持 2 个新方法:stream()、parallelStream(),返回流 java.util.stream.Stream。

 

流的使用包括 3 个元素:

  • 数据源,如集合

  • 中间操作链,形成一条流的流水线

  • 终端操作,执行流水线,并能生成结果

 

中间操作:返回另一个流,除非流水线上触发一个终端操作,否则中间操作不会执行任何处理,中间操作一般都可以合并起来,在终端操作时一次性全部处理。

中间操作的方法与作用如下:

方法名     返回类型       操作参数                   函数描述符        作用filter    Stream<T>    Predicate<T>              T -> boolean    过滤元素map       Stream<T>    Function<T, R>            T -> R          映射,将元素转换成其他形式或提取信息flatMap   Stream<T>    Function<T, Stream<R>>    T -> Stream<R>  扁平化流映射limit     Stream<T>    long                                      截断流,使其元素不超过给定数量skip      Stream<T>    long                                      跳过指定数量的元素sorted    Stream<T>    Comparator<T>             (T, T) -> int   排序distinct  Stream<T>                                              去重

 

终端操作:从流的流水线生成结果。

操作的方法与作用如下:

方法名      返回类型       操作参数                   函数描述符        作用anyMatch   boolean      Predicate<T>              T -> boolean    检查流中是否有一个元素能匹配给定的谓词allMatch   boolean      Predicate<T>              T -> boolean    检查谓词是否匹配所有元素noneMatch  boolean      Predicate<T>              T -> boolean    检查是否没有任何元素与给定的谓词匹配findAny    Optional<T>                                            返回当前流中的任意元素(用于并行的场景)findFirst  Optional<T>                                            查找第一个元素collect    R            Collector<T, A, R>                        把流转换成其他形式,如集合 List、Map、IntegerforEach    void         Consumer<T>               T -> void       消费流中的每个元素并对其应用 Lambda,返回 voidreduce     Optional<T>  BinaryOperator<T>         (T, T) -> T     归约,如:求和、最大值、最小值count      long                                                   返回流中元素的个数


 

构建流的方式

由值创建流

Stream<String> stream = Stream.of("a", "b", "c", "d");


由数组创建流

int[] numbers = {2, 3, 5, 7, 11, 13};int sum = Arrays.stream(numbers).sum();

 

由文件生成流

long uniqueWords = 0;Stream<String> lines = Files.lines(Paths.get("a.txt"), Charset.defaultCharset())){                uniqueWords = lines.flatMap(line -> Arrays.stream(line.split(" ")))                .distinct()                .count();


由函数生成流,创建无限流

Stream.iterate(0, n -> n + 2).limit(10).forEach(System.out::println);


Stream.generate(Math::random).limit(5).forEach(System.out::println);


为了避免了暗含的装箱成本,Java 8 还是推出了IntStream、DoubleStream和 LongStream,分别将流中的元素特化为 int、long 和 double,将原始类型流特化。

映射到数值流

double weight = list.stream()                    .mapToDouble(Fruit::getWeight)                    .sum();

 

转换回对象流

DoubleStream doubleStream = list.stream().mapToDouble(Fruit::getWeight);Streaing<Double> stream = doubleStream.boxed();

 

数值范围流,产生 1-100 之间的偶数

IntStream evenNumbers = IntStream.rangeClosed(1, 100)                                    .filter(n -> n % 2 == 0);

  

使用示例

package constxiong.interview;
import static java.util.Comparator.comparing;import static java.util.stream.Collectors.groupingBy;import static java.util.stream.Collectors.toList;
import java.util.Arrays;import java.util.List;import java.util.Map;import java.util.OptionalDouble;import java.util.stream.DoubleStream;import java.util.stream.IntStream;import java.util.stream.Stream;
/** * 测试 Stream 的API * @author ConstXiong */public class TestStreamAPI {
 public static void main(String[] args) {    List<Fruit> list = Arrays.asList(new Fruit("苹果", "红色", 1.1),        new Fruit("苹果", "绿色", 1.7),        new Fruit("香蕉", "黄色", 0.8),        new Fruit("香蕉", "绿色", 1.1),        new Fruit("橘子", "橙色", 0.7));
   //获取颜色为绿色的水果的类别,按照重量排序    System.out.println(list.stream()        .filter(f -> "绿色".equals(f.getColor()))        .sorted(comparing(Fruit::getWeight))        .map(Fruit::getType)        .collect(toList()));
   //利用多核架构并行执行这段代码,你只需要把stream()换成parallelStream()    //获取颜色为绿色的水果的类别,按照重量排序    System.out.println(list.parallelStream()        .filter(f -> "绿色".equals(f.getColor()))        .sorted(comparing(Fruit::getWeight))        .map(Fruit::getType)        .collect(toList()));
   //打印流的执行过程    list.parallelStream()        .filter(f -> {          System.out.println("filter:" + f);          return "绿色".equals(f.getColor());        })        .map(f -> {          System.out.println("map:" + f);          return f.getType();        })        .collect(toList());
   //按重量过滤,排序,取前 2 个水果    System.out.println(list.stream()        .filter(f -> f.getWeight() > 1)        .sorted(comparing(Fruit::getWeight))        .limit(2)        .collect(toList()));
   //按水果类型分组    Map<String, List<Fruit>> map = list.stream().collect(groupingBy(Fruit::getType));    System.out.println(map);
   //打印水果重量合计    double weight = list.stream()                      .mapToDouble(Fruit::getWeight)                      .sum();    System.out.println(weight);
   //转换回对象流    DoubleStream doubleStream = list.stream().mapToDouble(Fruit::getWeight);    Stream<Double> stream = doubleStream.boxed(); //包装成Double流
   //打印水果的最重重量    OptionalDouble maxWeight = list.stream()                .mapToDouble(Fruit::getWeight)                .max();    System.out.println(maxWeight.getAsDouble());
   //数值范围流,产生 1-100 之间的偶数    IntStream evenNumbers = IntStream.rangeClosed(1, 100)                      .filter(n -> n % 2 == 0);    evenNumbers.forEach(System.out::println);  }}


更多相关文章

  1. java8中的一个骚操作-方法引用(使代码看起来很高大上)
  2. 整理了一套操作系统常见的面试题,不管你是面试大厂还是小厂都足够
  3. mysql从入门到优化(3)事务的基本操作
  4. mysql从入门到优化(1)基本操作上
  5. mysql从入门到优化(4)视图的基本操作
  6. mysql从入门到优化(2)数据的增删改查操作总结

随机推荐

  1. 如何调用Android隐藏API
  2. AIDL的实现
  3. ubuntu下Android源代码模块编译
  4. [Android Develop_004] Android Backgrou
  5. Android系统服务概要
  6. Android(安卓)Low Memory Killer
  7. windows 8环境—android studio初步体验(
  8. Android核心分析 之十-------Android GWE
  9. Android EditText输入光标居于开头最开始
  10. Android 中自定义View(一)