一、简介

Stream API是在Java 8中引入的,为函数式编程提供便利。Stream API的目标是以函数方式处理对象的集合,根据定义,Stream是一个Java组件,可以对其元素进行内部迭代。

Stream(流)接口有终端方法和非终端方法,非终端方法是在流中添加监听器,当调用流的终端方法时,就会开始流元素的内部迭代,并对每个元素调用附加到流上的监听器,结果由终端方法收集。

1、中间方法

Stream接口中的非终端方法称为中间方法(Intermediate Methods),这种方法只能通过调用终端方法来调用。主要的中间方法如下:

  • filter

    根据给定的条件从流中过滤掉不需要的元素,此方法接受一个断言(Predicate)并将其应用于每个元素。如果断言函数返回true,则该元素包含在返回的流中。

  • map

    根据给定的函数将流的每个元素映射到另一个元素,此方法接受一个函数(Function)并将其应用于每个元素。例如,将流中的每个String元素转换为大写的String元素。

  • flatMap

    此方法可用于基于给定函数将流的每个元素映射到多个元素,当需要将复杂对象分解为简单对象时,会使用此方法。例如,将句子列表转换为单词列表。

  • distinct

    如果存在重复项,则返回一个唯一元素流。

  • limit

    返回指定限制个数的元素。

2、终端方法

当在流上调用终端方法时,迭代在stream或其他stream链上开始;迭代结束后,返回终端方法的结果,终端方法不返回流。

通常,终端方法返回一个值,并在流的每个元素上调用。每个终端函数都采用断言(Predicate)函数,启动元素的迭代,将断言应用于每个元素。主要的终端方法如下:

  • anyMatch

    如果任何一个元素满足断言,则返回true;如果所有元素都不满足,则返回falase。

  • allMatch

    当所有元素都满足断言时返回true,否则返回false。

  • noneMatch

    当所有元素都不满足断言时返回true,否则返回false。

  • collect

    将每个元素都存储到传递的集合中。

  • count

    返回通过中间方法传递的元素的个数。

  • findAny

    返回包含任一元素的Optional实例或空实例(空的stream返回空实例)。

  • findFirst

    返回包含第一个元素的Optional实例或空实例。

  • forEach

    将Consumer函数应用于每个元素。

  • reduce

    使用累加函数对流的元素执行归约(reduction),并返回Optional类型的归约值。

  • min

    通过传递的比较器断言比较元素,返回流中的最小元素,是一种特殊的reduction。

  • max

    通过传递的比较器断言比较元素,返回流中的最大元素,,是一种特殊的reduction。

  • toArray

    返回流中元素的数组。

3、固定长度流

可以通过以下方法创建固定长度的流:

  • Stream.of()
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
  • Collection.stream()
List<Integer> nums = Arrays.asList(new Integer[]{1, 2, 3, 4, 5});
Stream<Integer> stream = nums.stream();
  • Stream.builder()
Builder<Integer> builder = Stream.builder();
builder.accept(1);
builder.accept(2);
builder.accept(3);
builder.accept(4);
builder.accept(5);
Stream<Integer> stream = builder.build();

4、无限流

可以通过以下方法创建无限流:

  • Stream.iterate()
//3的倍数
Stream<Integer> stream = Stream.iterate(0, n -> n + 3);
stream.limit(10).forEach(System.out::println);
  • Stream.generate
//生成随机整数流
Stream<Integer> stream = Stream.generate(new Random()::nextInt);
stream.limit(10).forEach(System.out::println);

二、样例

1、中间方法

  • 代码
List<String> strs = Arrays.asList("One", "Two", "Three", "Four", "Five", "One");
//filter
Stream<String> longStrs = strs.stream().filter(str -> str.length() > 3);
longStrs.forEach(System.out::println);

//map
strs.stream().map(str -> str.toUpperCase()).forEach(System.out::println);

//flatMap
List<String> sentenceList = Arrays.asList("I am Mahesh.", "I love Java 8 Streams.");
sentenceList.stream().flatMap(sentence -> {return Arrays.asList(sentence.split(" ")).stream();}).forEach(System.out::println);

//distinct
strs.stream().distinct().forEach(System.out::println);

//limit
strs.stream().limit(2).forEach(System.out::println);
  • 运行结果
Three
Four
Five
ONE
TWO
THREE
FOUR
FIVE
ONE
I
am
Mahesh.
I
love
Java
8
Streams.
One
Two
Three
Four
Five
One
Two

2、终端方法

  • 代码
List<String> strs = Arrays.asList("One", "Two", "Three", "Four", "Five", "One");
//anyMatch 
System.out.println(strs.stream().anyMatch(str -> str.contains("ee")));

//allMatch
System.out.println(strs.stream().allMatch(str -> str.length() >= 3));

//noneMatch
System.out.println(strs.stream().noneMatch(str -> str.startsWith("A")));

//collect
strs.stream().filter(str -> str.length() > 3).collect(Collectors.toList()).forEach(System.out::println);;

//findAny
System.out.println(strs.stream().findAny().get());

//findFirst
System.out.println(strs.stream().findFirst().get());

//reduce
System.out.println(strs.stream().reduce((str, another) -> str + " " + another));

//min
System.out.println(strs.stream().min((str, another) -> str.compareTo(another)));

//max
System.out.println(strs.stream().max((str, another) -> str.compareTo(another)));

//toArray
System.out.println(strs.stream().toArray().getClass());
  • 运行结果
true
true
true
Three
Four
Five
One
One
Optional[One Two Three Four Five One]
Optional[Five]
Optional[Two]
class [Ljava.lang.Object;
参考资料

Intermediate Methods

Terminal Methods