筛选、切片、匹配、查找、匹配、归约

筛选:

numbers.stream()
.filter(i -> i % 2 == 0)
.distinct()
.forEach(System.out::println);

延伸:可以去掉distinct(),改用toSet()可以去掉distinct(),改用toSet()   transactions.stream().collect(toSet());

截短:

menu.stream()
.filter(d -> d.getCalories() > 300)
.limit(3)
.collect(toList());

跳过:

menu.stream()
.filter(d -> d.getCalories() > 300)
.skip(2)
.collect(toList());

映射:

  对流中每一个元素应用函数

  menu.stream()
  .map(Dish::getName)
  .collect(toList());

  流的扁平化(组合流):例如, 给定单词列表["Hello","World"],你想要返回列表["H","e","l", "o","W","r","d"] 

List<String> uniqueCharacters =
words.stream()
.map(w -> w.split(""))
.flatMap(Arrays::stream)
.distinct()
.collect(Collectors.toList());

  扩展举例:给定两个数字列表,如何返回所有的数对呢?例如,给定列表[1, 2, 3]和列表[3, 4],应该返回[(1, 3), (1, 4), (2, 3), (2, 4), (3, 3), (3, 4)]。然后,只返回总和能被3整除的数对呢?例如(2, 4)和(3, 3)是可以的。

List<Integer> numbers1 = Arrays.asList(1, 2, 3);
				List<Integer> numbers2 = Arrays.asList(3, 4);
				List<int[]> p = numbers1.stream()
						.flatMap(i -> numbers2.stream()
								.filter(j -> (i + j) % 3 == 0)//这两个,可以二选一
								.map(j -> new int[]{i,j}))
						.filter(list -> (list[0]+list[1])%3==0)//这两个,可以二选一
						.collect(toList());

查找和匹配:

  检查谓词是否至少匹配一个元素:anyMatch

anyMatch方法可以回答“流中是否有一个元素能匹配给定的谓词”。比如,你可以用它来看
看菜单里面是否有素食可选择:
if(menu.stream().anyMatch(Dish::isVegetarian)){
System.out.println("The menu is (somewhat) vegetarian friendly!!");
}
anyMatch方法返回一个boolean,因此是一个终端操作

  检查谓词是否匹配所有元素:allMatch noneMatch

anyMatch、allMatch和noneMatch这三个操作都用到了我们所谓的短路,这就是大家熟悉的Java中&&和||运算符短路在流中的版本。

  查找元素:findAny方法将返回当前流中的任意元素,是一个终端操作

Optional<Dish> dish =
	menu.stream()
	.filter(Dish::isVegetarian)
	.findAny()

  Optional<T>类(java.util.Optional)是一个容器类,代表一个值存在或不存在。Java 8的库设计人员引入了Optional<T>,这样就不用返回众所周知容易出问题的null了。

  查找第一个元素:findFirst()

何时使用findFirst和findAny
  你可能会想,为什么会同时有findFirst和findAny呢?答案是并行。找到第一个元素
  在并行上限制更多。如果你不关心返回的元素是哪个,请使用findAny,因为它在使用并行流时限制较少。

归约 / 折叠(fold)/ 将流归约成一个值

List<Integer> numbers = Arrays.asList(1, 2, 3);
int product = numbers.stream().reduce(0, (a, b) -> a + b);
Optional<Integer> sum = numbers.stream().reduce((a, b) -> (a + b));
Optional<Integer> max = numbers.stream().reduce(Integer::max);
Optional<Integer> min = numbers.stream().reduce(Integer::min);
Optional<Integer> min2 = numbers.stream().reduce((a, b) -> a>b?b:a);

 举例:计算出menu菜单中,一共多少菜品种

int count = menu.stream()
    .map(d -> 1)
    .reduce(0, (a, b) -> a + b);
或:
long count = menu.stream().count();

数值流:

   原始类型流特化:

    1. 映射到数值流   

    int calories = menu.stream()
    .mapToInt(Dish::getCalories)
    .sum();

    2. 转换回对象流

    IntStream intStream = menu.stream().mapToInt(Dish::getCalories);
    Stream<Integer> stream = intStream.boxed();

    3. 默认值OptionalInt

     OptionalInt maxCalories = menu.stream()
      .mapToInt(Dish::getCalories)
      .max();

 数值范围:IntStream和LongStream---------生成这种范围:range和rangeClosed。这两个方法都是第一个参数接受起始值,第二个参数接受结束值

IntStream evenNumbers = IntStream.rangeClosed(1, 100)
	.filter(n -> n % 2 == 0);
evenNumbers.forEach(i -> System.out.println(i));

构建流:

  由值创建流:

Stream<String> stream = Stream.of("Java 8 ", "Lambdas ", "In ", "Action");
stream.map(String::toUpperCase).forEach(System.out::println);

  由数组创建流:

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

  由文件生成流:例子,查看文件中有多少个不同的词

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

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

  1. 迭代(Stream API提供了两个静态方法来从函数生成流:Stream.iterate和Stream.generate。由iterate和generate产生的流会用给定的函数按需创建值

Stream.iterate(0, n -> n + 2)
.limit(10)   //限制最大值
.forEach(System.out::println);

  扩展:

	Stream.iterate(new int[]{0,1}, t -> new int[]{t[1],t[1]+t[0]})
	.limit(10)
	.forEach(d -> System.out.println(d[0]+","+d[1]));

  2. 生成

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

 

posted on 2017-11-27 17:02  一个帅哥9527  阅读(171)  评论(0编辑  收藏  举报