1、迭代

我们在遍历集合时,通常会使用到for循环。for循环其实是封装了Iterator迭代器的语法糖。是一种外部迭代。
外部迭代很难抽象出一些我们需要的操作,从本质上讲,它是一种串行化操作。

另一种方法就是内部迭代,也就是Stream的操作。

stream的操作大体可以分为两种:过滤和计数。如以下代码:
allArtists.stream().filter(artist -> artist.isFrom("London"));
只过滤,不计数。像 filter 这样只描述 Stream,最终不产生新集合的方法叫作惰性求值方法;而像 count 这样
最终会从 Stream 产生值的方法叫作及早求值方法。

下列代码只有惰性求值方法,所以程序并不会输出任何信息

  1. allArtists.stream() .filter(artist -> {
  2. System.out.println(artist.getName());
  3. return artist.isFrom("London");
  4. });

如果在其加入一个拥有终止操作的流,则会被输出

  1. long count = allArtists.stream() .filter(artist -> {
  2. System.out.println(artist.getName());
  3. return artist.isFrom("London");
  4. }).count();

如果返回值是 Stream, 那么是惰性求值;如果返回值是另一个值或为空,那么就是及早求值。

2、常用的流操作

collect(toList())

collect(toList())方法由Stream里的值生成一个列表,是一个及早求值操作

  1. List<String> collected = Stream.of("a", "b", "c") // 生成列表
  2. .collect(Collectors.toList()); // 聚合成一个list
  3. assertEquals(Arrays.asList("a", "b", "c"), collected);

map

如果有一个函数可以将一种类型的值转换成另外一种类型,map 操作就可以使用该函数,将一个流中的值转换成一个新的流。

用map操作将字符串转为大写形式

  1. List<String> collected = Stream.of("a", "b", "hello")
  2. .map(string -> string.toUpperCase())
  3. .collect(toList());
  4. assertEquals(asList("A", "B", "HELLO"), collected);

filter

遍历数据并检查其中的元素时,可尝试使用 Stream 中提供的新方法 filter

  1. List<String> beginningWithNumbers = Stream.of("a", "1abc", "abc1")
  2. .filter(value -> isDigit(value.charAt(0)))
  3. .collect(toList());

flatMap

flatMap 方法可用 Stream 替换值,然后将多个 Stream 连接成一个 Stream

将所有数字合成一个列表

  1. List<Integer> together = Stream.of(asList(1, 2), asList(3, 4))
  2. .flatMap(numbers -> numbers.stream())
  3. .collect(toList());

max和min

求最大最小值

  1. List<Track> tracks = asList(new Track("Bakai", 524),
  2. new Track("Violets for Your Furs", 378),
  3. new Track("Time Was", 451));
  4. Track shortestTrack = tracks.stream()
  5. .min(Comparator.comparing(track -> track.getLength()))
  6. .get();

reduce

  1. int count = Stream.of(1, 2, 3)
  2. .reduce(0, (acc, element) -> acc + element); // acc是累加器,保存着当前的累加结果
  3. assertEquals(6, count);