原创转载请注明出处:http://agilestyle.iteye.com/blog/2424918
Definition
A short definition is “a sequence of elements from a source that supports data processing operations.”
Sequence of elements — Like a collection, a stream provides an interface to a sequenced set of values of a specific element type. Because collections are data structures, they’re mostly about storing and accessing elements with specific time/space complexities (for example, an ArrayList vs. a LinkedList). But streams are about expressing computations such as filter, sorted, and map that you saw earlier. Collections are about data; streams are about computations.
Source — Streams consume from a data-providing source such as collections, arrays, or I/O resources.
Note that generating a stream from an ordered collection preserves the ordering. The elements of a stream coming from a list will have the same order as the list.
Data processing operations — Streams support database-like operations and common operations from functional programming languages to manipulate data, such as filter, map, reduce, find, match, sort, and so on. Stream operations can be executed either sequentially or in parallel.
Pipelining — Many stream operations return a stream themselves, allowing operations to be chained
and form a larger pipeline. This enables certain optimizations, such as laziness and short-circuiting. A pipeline of operations can be viewed as a database-like query on the data source.
Internal iteration — In contrast to collections, which are iterated explicitly using an iterator,
stream operations do the iteration behind the scenes for you.
Chaining stream operations forming a stream pipeline
e.g.
package org.fool.java8.stream;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
public class StreamTest1 {
public static void main(String[] args) {
List<Dish> menu = Arrays.asList(
new Dish("pork", false, 800, Dish.Type.MEAT),
new Dish("beef", false, 700, Dish.Type.MEAT),
new Dish("chicken", false, 400, Dish.Type.MEAT),
new Dish("french fries", true, 530, Dish.Type.OTHER),
new Dish("rice", true, 350, Dish.Type.OTHER),
new Dish("season fruit", true, 120, Dish.Type.OTHER),
new Dish("pizza", true, 550, Dish.Type.OTHER),
new Dish("prawns", false, 300, Dish.Type.FISH),
new Dish("salmon", false, 450, Dish.Type.FISH) );
List<String> lowCaloricDishesName = menu.parallelStream()
.filter(d -> d.getCalories() < 400)
.sorted(Comparator.comparing(Dish::getCalories))
.map(Dish::getName)
.collect(Collectors.toList());
System.out.println(lowCaloricDishesName);
}
public static class Dish {
private String name;
private boolean vegetarian;
private int calories;
private Type type;
public Dish(String name, boolean vegetarian, int calories, Type type) {
this.name = name;
this.vegetarian = vegetarian;
this.calories = calories;
this.type = type;
}
public enum Type { MEAT, FISH, OTHER }
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isVegetarian() {
return vegetarian;
}
public void setVegetarian(boolean vegetarian) {
this.vegetarian = vegetarian;
}
public int getCalories() {
return calories;
}
public void setCalories(int calories) {
this.calories = calories;
}
public Type getType() {
return type;
}
public void setType(Type type) {
this.type = type;
}
@Override
public String toString() {
return "Dish{" +
"name='" + name + '\'' +
", vegetarian=" + vegetarian +
", calories=" + calories +
", type=" + type +
'}';
}
}
}
Console Output
[season fruit, prawns, rice]
稍作改动,让程序sleep一段时间
...
List<String> lowCaloricDishesName =
menu.parallelStream()
.filter(d -> {
try {
Thread.sleep(10000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return d.getCalories() < 400;
})
.sorted(Comparator.comparing(Dish::getCalories))
.map(Dish::getName)
.collect(Collectors.toList());
System.out.println(lowCaloricDishesName);
...
运行程序,打开jconsole,观察一下线程
连接
可以看到底层使用的是ForkJoin实现
Filtering a menu using a stream to find out three high-calorie dish names
e.g.
List<String> lowCaloricDishesName = menu.parallelStream()
.filter(d -> d.getCalories() > 300)
.sorted(Comparator.comparing(Dish::getCalories))
.map(Dish::getName)
.limit(3)
.collect(Collectors.toList());
Console Output
[rice, chicken, salmon]
Intermediate operations
Intermediate operations such as filter or sorted return another stream as the return type. This allows the operations to be connected to form a query. What’s important is that intermediate operations don’t perform any processing until a terminal operation is invoked on the stream pipeline—they’re lazy. This is because intermediate operations can usually be merged and processed into a single pass by the terminal operation.
Terminal operations
Terminal operations produce a result from a stream pipeline. A result is any nonstream value such as a List, an Integer, or even void.
Reference
Manning.Java.8.in.Action.Lambdas.Streams.and.functional-style.programming