Java8 StreamAPI看这一篇就够了

简介

Stream是Java 8的一大亮点,与 java.io包中的InputStream和OutputStream不同,Java 8中的Stream是对集合对象功能的增强,专注于对集合对象进行各种非常便利、高效的聚合操作,或者大批量数据操作。Stream API借助于同样新出现的Lambda表达式,极大地提高编程效率

食用

使用StreamAPI分三步

  • 获得个流
  • 中间操作
  • 终止操作

获得流

使用如下方法可以获得流

  • 通过java.util.Collection提供的stream()或parallelStream()方法获得一个流
  • 通过java.util.Arrays提供的stream()方法将一个数组转换成流
  • 通过java.util.stream.Stream提供的of()方法得到一个流
  • 通过java.util.stream.Stream提供的iterate()方法获取一个流
  • 通过java.util.stream.Stream提供的generate()方法获取一个流

代码演示

// 1, 通过java.util.Collection提供的stream()或parallelStream()方法获得一个流
List<String> list = Lists.newArrayList("Jack", "Tom");
Stream<String> stream1 = list.stream();
Stream<String> stream2 = list.parallelStream();

// 2, 通过java.util.Arrays提供的stream()方法将一个数组转换成流
String[] arr = {"Jack", "Tom"};
Stream<String> stream3 = Arrays.stream(arr);

// 3, 通过java.util.stream.Stream提供的of()方法得到一个流
Stream<String> stream4 = Stream.of("Jack", "Tom");

// 4, 通过java.util.stream.Stream提供的iterate()方法获取一个流
Stream<Integer> stream5 = Stream.iterate(0, (x) -> x + 5);

// 5, 通过java.util.stream.Stream提供的generate()方法获取一个流
Stream<Double> stream6 = Stream.generate(Math::random);

中间操作

多个中间操作连起来类似一个流水线,在终止操作之前,中间操作不会对数据进行任何处理,直到终止操作时才会一次性全部处理中间操作

  • 过滤、截取、跳过、去重
  • 映射
  • 排序

代码演示

List<Student> list = Lists.newArrayList(new Student(1001L, 20, "Jack"),
        new Student(1002L,25, "Tom"),
        new Student(1003L,30, "Bob"),
        new Student(1004L,35, "Chen"),
        new Student(1004L,35, "Chen"));

// 中间操作 .filter() 过滤流中的元素; .limit() 截取流中的元素; .skip() 跳过元素; .distinct() 元素去重
Stream<Student> stream = list.stream()
        .filter((s) -> s.getAge() >= 25)
        .limit(5)
        .skip(1)
        .distinct();
// 终止操作
stream.forEach(System.out::println);


// 中间操作 .map() 映射; .flatMap() 将多个流转换为1个流; .mapToDouble(); .mapToInt(); .mapToLong()
Stream<Character> stream1 = list.stream()
        .map(Student::getName)
        .flatMap(StreamApiTest::nameCharacter);
// 终止操作
stream1.forEach(System.out::println);


// 中间操作 .sorted() 自然排序; .sorted() 自定义排序
Stream<Student> stream2 = list.stream()
        .sorted(Comparator.comparingInt(Student::getAge));
// 终止操作
stream2.forEach(System.out::println);

// 补充
private static Stream<Character> nameCharacter(String name) {
    List<Character> cList = Lists.newArrayList();
    for (Character c : name.toCharArray()) {
        cList.add(c);
    }
    return cList.stream();
}

终止操作

  • 匹配、查找、统计、遍历
  • 规约
  • 收集

代码演示

List<Student> list = Lists.newArrayList(new Student(1001L, 20, "Jack"),
        new Student(1002L,25, "Tom"),
        new Student(1003L,10, "Bob"),
        new Student(1004L,35, "Chen"),
        new Student(1004L,35, "Chen"));

Stream<Student> stream = list.stream()
        .filter((s) -> s.getAge() >= 25);

// 终止操作
// .allMatch() 是否全部元素匹配; .anyMatch() 是否至少一个元素匹配; .noneMatch() 是否所有元素都不匹配;
// .findAny() 返回任意一个元素; .findFirst() 返回第一个元素
// .count() 返回元素总数
// .max() 返回最大元素; .min() 返回最小元素
// .forEach() 内部迭代所有元素
boolean j = stream
        .anyMatch((s) -> s.getName().contains("C"));
System.out.println(j);

// 终止操作 .reduce() 将流中的元素结合起来
int sum = stream
        .mapToInt(Student::getAge)
        .reduce(0, Integer::sum);
System.out.println(sum);

// 终止操作 .collect() 将元素汇总
// 收集到List
List<Student> collect = stream.collect(Collectors.toList());
// 收集到Set
Set<Student> collect1 = stream.collect(Collectors.toSet());
// 收集到创建的集合
ArrayList<Student> collect2 = stream.collect(Collectors.toCollection(ArrayList::new));
// 收集元素的个数
Long collect3 = stream.collect(Collectors.counting());
// 求和
Integer collect4 = stream.collect(Collectors.summingInt(Student::getAge));
// 求平均值
Double collect5 = stream.collect(Collectors.averagingInt(Student::getAge));
// 得到统计值
IntSummaryStatistics collect6 = stream.collect(Collectors.summarizingInt(Student::getAge));
// 连接字符串
String collect7 = stream.map(Student::getName).collect(Collectors.joining());
// 得到最大值
Optional<Student> collect8 = stream.collect(Collectors.maxBy(Comparator.comparingInt(Student::getAge)));
// 得到最小值
Optional<Student> collect9 = stream.collect(Collectors.minBy(Comparator.comparingInt(Student::getAge)));
// 规约
Integer collect10 = stream.collect(Collectors.reducing(0, Student::getAge, Integer::sum));
// 对收集器的结果进行转换
Integer collect11 = stream.collect(Collectors.collectingAndThen(Collectors.toList(), List::size));
// 转map
Map<Long, List<Student>> collect12 = stream.collect(Collectors.groupingBy(Student::getId));
// boolean区分
Map<Boolean, List<Student>> collect13 = stream.collect(Collectors.partitioningBy((s) -> s.getAge() > 20));

补充

串行流与并行流:可以通过 .sequential() 和 .parallel() 在串行流与并行流之间做切换

代码演示

StopWatch watch = new StopWatch();
watch.start("耗时");

LongStream stream = LongStream.rangeClosed(0, 10000000000L);
long sum = stream
        .parallel()
        .reduce(0, Long::sum);

watch.stop();
// .sequential() 耗时18225ms; .parallel() 耗时892ms
System.out.println(watch.prettyPrint());

你可能感兴趣的:(Java)