第三章 流Stream

第三章 流

java8中新增的特性是想在帮助程序员写出更好的代码,其中对核心类库的改进是很关键的一部分,也是本章的主要内容。

对核心类库的改进主要包括集合类的API和新引入的流(Stream)。

流使得我们可以在更高的抽象层次对集合进行操作

通常,以前,我们是这样使用for循环计算来自London的人数:

int count = 0;
for (Artist artist : allArtists) {
    if (artist.isFrom("London")) {
        count++;
    }
}

背后原理,其实是用for循环封装了迭代的语法糖(外部迭代):

int count = 0;
Iterator iterator = allArtists.iterator();
while (iterator.hasNext()) {
    Artist artist = iterator.next();
    if (artist.isFrom("London")) {
        count++;
    }
}

java8中使用stream(),返回的是内部迭代的接口:Stream。

long count=allArtists.stream()
                    .filter(artist->artist.isForm("London"))
                    .count();

stream()方法是Collection接口里面的default方法

default Stream stream() {
    return StreamSupport.stream(spliterator(), false);
}

惰性求值,如下运行不会输出任何信息:

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

只有加上count(),才会输出:

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

判断一个操作是惰性求值还是及早求值:只需看它的返回值,如果返回的是Stream,那么是惰性求值;如果返回值是另一个值或者为空,那么就是及早求值。

跟建造者模式有点类似,最后调用一个build()方式时,才会创建对象。

常用的流操作

collect(toList())

    List<String> collected = Stream.of("a", "b", "c") // <1>
            .collect(Collectors.toList()); // <2>

    assertEquals(Arrays.asList("a", "b", "c"), collected); // <3>

map

    List<String> collected = Stream.of("a", "b", "hello")
            .map(string -> string.toUpperCase()) // <1>
            .collect(toList());

    assertEquals(asList("A", "B", "HELLO"), collected);

传给map的Lambda表达式是函数式接口Function的一个实例:

   <R> Stream<R> map(Function super T, ? extends R> mapper);
 其中Function 部分源码:
    public interface Function {

        /**
         * Applies this function to the given argument.
         *
         * @param t the function argument
         * @return the function result
         */
        R apply(T t);

filter

使用老的for循环

   List beginningWithNumbers = new ArrayList<>();
    for (String value : asList("a", "1abc", "abc1")) {
        if (isDigit(value.charAt(0))) {
            beginningWithNumbers.add(value);
        }
    }

函数式风格:

   List together = Stream.of("a", "1abc", "abc1")
                            .filter(value->isDigit(value.charAt(0)))
                            .collect(toList());

    assertEquals(asList(1, 2, 3, 4), together);

其中filter()接收的是一个叫predicate的函数接口

flatMap

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

    assertEquals(asList(1, 2, 3, 4), together);

这个不怎么好理解,flatMap规定lambda返回的是Stream类型。而作用是拆解原来的流,然后组合成一个新的流。

max,min

 List tracks = asList(new Track("Bakai", 524),
            new Track("Violets for Your Furs", 378),
            new Track("Time Was", 451));

    Track shortestTrack = tracks.stream()
            .min(Comparator.comparing(track -> track.getLength()))
            .get();

    assertEquals(tracks.get(1), shortestTrack);

使用以前的方法:

  tracks.sort(new Comparator() {
        @Override
        public int compare(Track o1, Track o2) {
           //比较逻辑
        }
    });

然后再从tracks里面取出最小的。

或者可以直接用Collections.min()

    Collections.min(tracks, new Comparator() {
        @Override
        public int compare(Track o1, Track o2) {
            //比较逻辑
        }
    })

但还是java8的好看

整合起来的操作:

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

    assertEquals(asList("1abc"), beginningWithNumbers);

你可能感兴趣的:(java8,java,java8,Stream)