The Java SE 8 Stream Library

来源:互联网 发布:java简单小游戏 编辑:程序博客网 时间:2024/06/06 03:17

Stream Introduction

Streams provide a view of data that lets you specify computations at a higher conceptual level than with collections.
With a stream, you specify what you want to have done, not how to do it.
You leave the scheduling of operations to the implementation.

Count long words in an iterating way:

public class CountLongWords {       public static void main(String[] args) throws IOException {             String contents = new String(Files.readAllBytes(Paths.get("gutenberg/alice30.txt")),StandardCharsets.UTF_8);        List<String> words = Arrays.asList(contents.split("\\PL+"));        long count = 0;        for (String w : words) {            if (w.length() > 12)                count++;        }        System.out.println(count);      }   }

Count long words in a stream way:

public class CountLongWords {       public static void main(String[] args) throws IOException {             String contents = new String(Files.readAllBytes(Paths.get("gutenberg/alice30.txt")),StandardCharsets.UTF_8);        List<String> words = Arrays.asList(contents.split("\\PL+"));        long count = 0;        count = words.stream().filter(w -> w.length() > 12).count();        System.out.println(count);    }   }

Count long words in a parallel stream way:

count = words.parallelStream().filter(w -> w.length() > 12).count();

A stream seems superficially similar to a collection, but there are significant differences:

  1. A stream does not store its elements.
  2. Stream operations do not mutate their source. For example, the filter method does not remove elements from a new stream, but it yields a new stream in which they are not present.
  3. Stream operations are lazy when possible. This means they are not executed until their result is needed.

When working with streams, you set up a pipeline of operations in three stages:

  1. Create a stream.
  2. Specify intermediate operations for transforming the initial stream into others, possibly in multiple steps.
  3. Apply a terminal operation to produce a result. This operation forces the execution of the lazy operations that precede it. Afterwards, the stream can no longer be used.

Stream Creation

1 The stream() method of the Collection interface can turn any collection into a stream.

count = words.stream().filter(w -> w.length() > 12).count();

2 The static Stream.of method can make a stream from an array.
This method has a varargs parameter, so you can construct a stream from any number of arguments:

Stream<String> words = Stream.of(contents.split("[\\P{L}]+"));
Stream<String> song = Stream.of("gently", "down", "the", "stream");

3 The Arrays.stream(array, from, to) method can make a stream from a part of an array.

Stream<String> parts = Arrays.stream(contents.split("\\PL+"), 0, 6);        

4 The static Stream.empty method can make a stream with no elements.

Stream<String> silence = Stream.empty();

5 The Stream.generate method can make an infinite stream.
This method takes a function with no arguments (an object of the Supplier interface).
Whenever a stream value is needed, that function is called to produce a value.

Stream<String> echos = Stream.generate(() -> "Echo");Stream<Double> randoms = Stream.generate(Math::random);

6 The Stream.iterate method can produce infinite sequences.
It takes a seed value and a function ( a UnaryOperator) and repeatedly applies the function to the previous result.

Stream<BigInteger> integers = Stream.iterate(BigInteger.ONE,     n -> n.add(BigInteger.ONE));

7 the Pattern class has a method splitAsStream that splits a CharSequence by a regular expression.

Stream<String> wordsAnotherWay = Pattern.compile("\\PL+").splitAsStream(contents);

8 The static Files.lines method returns a Stream of all lines in a file.

try (Stream<String> lines = Files.lines(path)){    //Process lines}

Stream Transformation

A stream transformation produces a stream whose elements are derived from those of another stream.

1 filter, map and flatMap

The filter method yields a new stream with those elements that match a certain condition.
The argument of filter is a Predicate—that is, a function from T to boolean.

count = words.stream().filter(w -> w.length() > 12).count();

Often, you want to transform the values in a stream in some way.
Use the map method and pass the function that carries out the transformation.

Stream<String> lowercaseWords = words.stream()    .map(String::toLowerCase);
Stream<String> firstLetters = words.stream()    .map(s -> s.substring(0, 1));

Now, suppose you have a function that returns not just one value but a stream of values

public static Stream<String> letters(String s){    List<String> result = new ArrayList<>();    for (int i = 0; i < s.length(); i++)        result.add(s.substring(i, i + 1));    return result.stream();}

Suppose you map the letters method on a stream of strings

Stream<Stream<String>> result = words.stream().map(w -> letters(w));

You will get a stream of streams, like [… [“y”, “o”, “u”, “r”], [“b”, “o”, “a”, “t”], …]

To flatten it out to a stream of letters [… “y”, “o”, “u”, “r”, “b”, “o”, “a”, “t”, …], use the flatMap method instead of map:

Stream<String> flatResult = words.stream().flatMap(w -> letters(w))

2 limit, skip and concat

The stream.limit(n) returns a new stream that ends after n elements .

Stream<Double> randoms = Stream.generate(Math::random).limit(100);

The stream.skip(n) discards the first n elements.

Stream<String> words = Stream.of(contents.split("[\\P{L}]+")).skip(1);

The static concat method of the Stream class can concatenate two streams.

Stream<String> combined = Stream.concat(letters("Hello"), letters("World"));

3 distinct, sorted and peek

The distinct method returns a stream that yields elements from the original stream, in the same order, except that duplicates are suppressed.

Stream<String> uniqueWords = Stream.of("merrily", "merrily", "merrily", "gently").distinct();

There are several variations of the sorted method.
One works for streams of Comparable elements, and another accepts a Comparator.

Stream<String> longestFirst =words.stream().sorted(Comparator.comparing(String::length).reversed());

Finally, the peek method yields another stream with the same elements as the original, but a function is invoked every time an element is retrieved.
For debugging, you can have peek call a method into which you set a breakpoint.

Object[] powers = Stream.iterate(1.0, p -> p * 2)    .peek(e -> System.out.println("Fetching " + e))    .limit(20).toArray();
原创粉丝点击