聊一下Java8中的Stream

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.实例

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章