1.从外部迭代到内部迭代
外部迭代
for循环其实是封装了一个迭代的语法糖
int count =0;
Iterator<Artist> iterator = allArtists.iterator;
while(iterator.hasNext()){
Artist artist = iterator.next();
if(artist.isForm("Cter")){
count++;
}
}
首先调用iterator方法 产生一个新的Iterador对象,近而控制整个迭代过程,这就是外部迭代。
内部迭代
long count = allArtists.stream()
.filter(artist -> artist.isForm("Cter"))
.count();
Stream 是用函数式编程方式在集合类上进行复杂操作的工具
2.实现机制
内部迭代的代码中 整个过程被分解为两种更简单的操作:过滤和计数 ,看似有化简为繁之嫌 与外部迭代的一次for循环相比 两种操作是否意味着两次循环? 其实不是 这只是一次循环
通常来说在java中调用一个方法 计算机会随即执行操作 比如Syso(“hello world”) Stream里面的一些方法却略有不同。它们虽然是普通的java方法,但返回的stream对象却不是一个新集合,而是创建新集合的配方。
allArtists.stream()
.filter(artist -> artist.isForm("Cter"));
这行代码并没有实际性的操作,filter只刻画出了Stream,但没有产生新的集合。像filter这样只描述Stream,最终不产生新集合的方法叫做惰性求值方法;而像count这样最终会从Stream产生值的方法叫做及早求值方法
看下面代码
long count = allArtists.stream()
.filter(artist -> {
System.out.print("artist.getName()");
return artist.isForm("Cter")
});
运行这段代码,程序不会输出任何信息
如果将同样的输出语句加入一个拥有终止操作的流中,如下,艺术家的名字就会被输出
long count = allArtists.stream()
.filter(artist -> {
System.out.print("artist.getName()");
return artist.isForm("Cter")
})
.count();
判断惰性求值还是及早求值 只需要看它的返回值,如果返回值是Stream,那么就是惰性求值;如果返回值是另一个值或者空,那么就是及早求值
使用这些操作的理想方法就是形成一个惰性求值的链,最后用一个及早求值返回想要的结果,整个过程和构造者模式有共通之处。
3.常用的流操作
3.1 collect(toList())
collect(toList()) 方法由Stream里的值生成一个列表,是一个及早求值操作
List<String> collected = Stream.of("a","b")
.collect(Collectors.toList());
assertEquals(Arrays.asList("a","b"),collectd);
Stream 中of方法使用一组初始值生成新的Stream。
3.2 map
如果有一个函数可以将一种类型的值转换成另外一种类型,map操作就可以使用该函数,将一个流中的值转换成一个新的流。
Lits<String> collected = new ArrayList<>();
for(String string:asList("a","b")){
String uppercaseString = string.toUpperCase();
collected.add(uppercaseString);
}
使用新的流框架将一组字符转换成大写形式
List<String> collected = Stream.of("a","b")
.map(string -> string.toUpperCase())
.collect(toList());
3.3 filter
遍历数据并检查其中的元素时
之前的形式
Lits<String> beginningWithNumbers= new ArrayList<>();
for(String string:asList("a","b")){
if(isDigit(value.charAt(0))){
beginningWithNumbers.add(string);
}
}
使用filter
List<String> beginningWithNumbers= Stream.of("a","b")
.filter(string -> isDigit(value.charAt(0)))
.collect(toList());
3.4 flatMap
flatMap方法可用Stream替换值,然后将多个Stream连接成一个Stream
List<Integer> together= Stream.of(asList(1,2),asList(3,4))
.flatMap(numbers -> numbers.stream())
.collect(toList());
3.5 max和min
查找Stream中的最大元素和最小元素
Track shortestTrack = tracks.stream()
.min(Compartor.comparing(tarck -> track.getLength()))
.get();
3.6通用模式 reduce
reduce操作可以实现从一组值中生成一个值,在上面的例子中 count min max方法都是reduce操作。
reduce求和
int count = Stream.of(1,2,3)
.reduce(0,(acc,element) ->acc+element);
lambda表达式的返回值是最新的acc,是上一轮acc的值和当前元素相加的结果
展开reduce操作
BinaryOperator<Integer> accumulator = (acc,element) ->acc+element;
int count = accumulator.apply(
accumulator.apply(
accumulator.apply(0,1),
2),
3);
4.实例