流式是什么

流是Java API新成员,允许以声明的方式处理数据集合。主要特点:

  • 流水线-多个操作可以链接起来形成一个流水线
  • 内部迭代

比如:获取卡路里小于400的菜名并按卡路里排序(升序)。

Java8之前

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// 筛选<400
List< Dish> lowCaloricDishes = new ArrayList<>(); 
for( Dish d: menu){ 
	if( d. getCalories() < 400){
		lowCaloricDishes. add( d); 
	} 
} 

// 排序
Collections.sort( lowCaloricDishes, new Comparator< Dish>() {
public int compare( Dish d1, Dish d2){ 
 	return Integer. compare( d1. getCalories(), d2. getCalories()); 
}); 

// 获取名称
List< String> lowCaloricDishesName = new ArrayList<>(); 
for( Dish d: lowCaloricDishes){ 
	lowCaloricDishesName. add( d. getName()); 
}

Java8之后

1
2
3
4
5
6
7
import static java.util.Comparator.comparing; 
import static java.util.stream. Collectors.toList; 
List< String> lowCaloricDishesName = menu.stream()
	.filter( d -> d. getCalories() < 400)
	.sorted( comparing( Dish:: getCalories))
	.map( Dish:: getName)
	.collect( toList());

流与集合的区别

  • 只能迭代一次 VS 多次重复迭代使用
  • 内部迭代 VS 外部迭代
    • 内部迭代-可以自动选择一种适合你硬件的数据表示和并行实现。
    • 外部迭代-显式的对每个项进行处理。

流的操作

  • 中间操作,例如:filterlimitsorteddistinctmap
  • 终端操作,例如:collectforEachcount

示例

1
2
3
4
5
6
7
8
9
List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
        //获取流
        numbers.stream()
        		//中间操作
        		.filter(integer -> integer % 2 == 0)
        		//中间操作
                .distinct()
                //终端操作
                .forEach(System.out:: println);

总之流的使用包括三件事:

  • 一个数据源(集合等),执行数据查询。
  • 一个中间操作链,形成一条数据处理流水线。
  • 一个终端操作,执行流水线并形成结果。

示例所需基础代码

Dish.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class Dish {
    private final String name;
    private final boolean vegetarian;
    private final int calories;
    private final 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 String getName() {
        return name;
    }

    public boolean isVegetarian() {
        return vegetarian;
    }

    public int getCalories() {
        return calories;
    }

    public Type getType() {
        return type;
    }

    public enum Type {
        MEAT, FISH,OTHER
    }

    @Override
    public String toString() {
        return "Dish{" +
                "name='" + name + '\'' +
                ", vegetarian=" + vegetarian +
                ", calories=" + calories +
                ", type=" + type +
                '}';
    }
}

menu变量

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
static 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));