初体验
import java.util.*;
import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.toList;
/**
* 筛选热量高的菜肴
* Dish按照价格筛选,然后卡路里排序,最后做成菜单
*/
public class Demo {
// java8之前
public static List<String> filter1(List<Dish> menus){
List<Dish> lowCalories = new ArrayList<>();
for (Dish dish : menus) {
if (dish.getCalories()>100){
lowCalories.add(dish);
}
}
Collections.sort(lowCalories, new Comparator<Dish>() {
@Override
public int compare(Dish o1, Dish o2) {
return Integer.compare(o1.getPrice(),o2.getPrice());
}
});
List<String> lowCaloricDishesName = new ArrayList<>();
for (Dish dish : lowCalories) {
lowCaloricDishesName.add(dish.getName());
}
return lowCaloricDishesName;
}
//java8
public static List<String> filter2(List<Dish> menus) {
List<String> lowCaloricDishesName = menus.stream()
.filter(dish -> dish.getCalories()>100)
.sorted(comparing(Dish::getPrice))
.map(Dish::getName)
.limit(2)//只选头2个
.collect(toList());//将结果保存在另一个list中
return lowCaloricDishesName;
}
//java8 利用多核架构并行执行
public static List<String> filter3(List<Dish> menus) {
List<String> lowCaloricDishesName = menus.parallelStream()
.filter(dish -> dish.getCalories()>100)//筛选
.sorted(comparing(Dish::getPrice))
.map(Dish::getName)//提取,将元素转换成其他形式或提取信息
.collect(toList());//将流转换为列表
return lowCaloricDishesName;
}
public static void main (String[]args){
List<Dish> menus = Arrays.asList(
new Dish("aaa", 120, 30),
new Dish("ccc", 140, 20),
new Dish("bbb", 90, 10),
new Dish("ddd", 130, 50)
);
System.out.println(filter1(menus));
System.out.println(filter2(menus));
System.out.println(filter3(menus));
}
static class Dish{
private String name;
private Integer calories;
private Integer price;
public Dish(String name, Integer calories, Integer price) {
this.name = name;
this.calories = calories;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getCalories() {
return calories;
}
public void setCalories(Integer calories) {
this.calories = calories;
}
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
@Override
public String toString() {
return "Menu{" +
"name='" + name + '\'' +
", calories=" + calories +
", price=" + price +
'}';
}
}
}
流只能消费一次
/**
* 流只能消费一次
*/
public class Demo2 {
public static void main(String[] args){
List<String> title = Arrays.asList("a","b","c");
Stream<String> stream = title.stream();
stream.forEach(System.out::println);
stream.forEach(System.out::println);//Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
}
}
内部迭代与外部迭代
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
/**
* 外部迭代与内部迭代
* Streams库的内部迭代可以自动选择一种适 合你硬件的数据表示和并行实现
* 流利用内部迭代:迭代通过filter、map、sorted等操作被抽象掉了
* 通过写for-each而选择了外部迭代,那基本上就要自己管理所有的并行问题了(自己管理实际上意味着“我们会把它并行化” 或“开始了关于任务和synchronized的漫长而艰苦的斗争”)
*/
public class Demo3 {
public static void main(String[] args){
List<String> title = Arrays.asList("a","b","c");
// for-each循环外部迭代
for (String s : title) {
System.out.println(s);
}
// 迭代器外部迭代
Iterator<String> iterator = title.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
// 流 内部迭代
title.stream().collect(Collectors.toList());
}
}
总结
- 流是“从支持数据处理操作的源生成的一系列元素”。
- 流利用内部迭代:迭代通过filter、map、sorted等操作被抽象掉了。
- 流操作有两类:中间操作和终端操作。
- filter和map等中间操作会返回一个流,并可以链接在一起。可以用它们来设置一条流水线,但并不会生成任何结果。
- forEach和count等终端操作会返回一个非流的值,并处理流水线以返回结果。
- 流中的元素是按需计算的。