筛选:
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);