Streams make use of internal iteration: the iteration is abstracted away through operations such as filter, map, and sorted.
There are two types of stream operations: intermediate and terminal operations.
Intermediate operations such as filter and map return a stream and can be chained together. They’re used to set up a pipeline of operations but don’t produce any result.
Terminal operations such as forEach and count return a nonstream value and process a stream pipeline to return a result.
The elements of a stream are computed on demand.
You can filter and slice a stream using the filter, distinct, skip, and limit methods.
You can extract or transform elements of a stream using the map and flatMap methods.
You can find elements in a stream using the findFirst and findAny methods. You can match a given predicate in a stream using the allMatch, noneMatch, and anyMatch methods.
These methods make use of short-circuiting: a computation stops as soon as a result is found; there’s no need to process the whole stream.
You can combine all elements of a stream iteratively to produce a result using the reduce method, for example, to calculate the sum or find the maximum of a stream.
Some operations such as filter and map are stateless; they don’t store any state. Some operations such as reduce store state to calculate a value. Some operations such as sorted and distinct also store state because they need to buffer all the elements of a stream before returning a new stream. Such operations are called stateful operations.
There are three primitive specializations of streams: IntStream, DoubleStream, and LongStream. Their operations are also specialized accordingly.
Examples
/** get dish names that have less than 400 calories sorted by calories */
public static List<String> getLowCaloricDishesNames(List<Dish> dishes) {
return dishes.stream()
.filter(d -> d.getCalories() < 400)
.sorted(Comparator.comparing(Dish::getCalories))
.map(Dish::getName)
.collect(Collectors.toList());
}
//* finds the first square that’s divisible by 3 */
List<Integer> numbers= Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> firstSquareDivisibleByThree = numbers.stream()
.map(x -> x * x)
.filter(x -> x % 3 == 0)
.findFirst(); // 9
/** sum the elements of a list of numbers */
List<Integer> numbers = Arrays.asList(3,4,5,1,2);
int sum = numbers.stream().reduce(0, Integer::sum);
The problem with this code is that there’s an insidious boxing cost. Behind the scenes each Integer needs to be unboxed to a primitive before performing the summation - better to call sum method on stream:
int sum = numbers.stream().sum();
// find maximum element using reduce function
int max = numbers.stream().reduce(0, (a, b) -> Integer.max(a, b));
// when there is no initial value, return value is Optional
Optional<Integer> min = numbers.stream().reduce(Integer::min);
min.ifPresent(System.out::println);
// count using map-reduce pattern
int count = numbers.stream().map(d -> 1).reduce(0, (a, b) -> a + b);
Common data processing idiom is finding whether some elements in a set of data match a given property. The Streams API provides such facilities through the allMatch, anyMatch, noneMatch, findFirst, and findAny methods of a stream.
The anyMatch method can be used to answer the question “Is there an element in the stream matching the given predicate?”
List<Integer> numbers = Arrays.asList(3,4,5,1,2);
boolean anyMatch = numbers.stream().anyMatch(n -> n == 5);
Creating streams
Streams can be created not only from a collection but also from values, arrays, files, and specific methods such as iterate and generate.// Stream.of
Stream<String> stream = Stream.of("Java 8", "Lambdas", "In", "Action");
stream.map(String::toUpperCase).forEach(System.out::println);
// Stream.empty
Stream<String> emptyStream = Stream.empty();
// Arrays.stream
int[] numbers = {2, 3, 5, 7, 11, 13};
System.out.println(Arrays.stream(numbers).sum());
The Streams API provides two static methods to generate a stream from a function: Stream.iterate and Stream.generate. These two operations let you create what we call an infinite stream: a stream that doesn’t have a fixed size like when you create a stream from a fixed collection.
// Stream.iterate
Stream.iterate(0, n -> n + 2)
.limit(10)
.forEach(System.out::println);
// stream of 1s with Stream.generate
IntStream.generate(() -> 1)
.limit(5)
.forEach(System.out::println);
// fibonnaci with iterate
Stream.iterate(new int[]{0, 1}, t -> new int[]{t[1],t[0] + t[1]})
.limit(10)
. map(t -> t[0])
.forEach(System.out::println);
// find out the number of unique words in a file
Files.lines(Paths.get("/data.txt"), Charset.defaultCharset())
.flatMap(line -> Arrays.stream(line.split(" ")))
.distinct()
.count();
You use flatMap to produce one flattened stream of words instead of multiple streams of words for each line.
Ref
Java 8 in Action bookhttp://www.baeldung.com/java-8-streams
http://www.mkyong.com/java8/java-8-streams-filter-examples/
No comments:
Post a Comment