流只能遍历一次。遍历完之后,我们就说这个流已经被消费掉了,重新生成流
List<String> names = menu.stream()
.filter(d -> d.getCalories() > 300)
.map(Dish::getName)
.limit(3)
.collect(Collectors.toList());
filter、map和limit可以连成一条流水线(中间操作),collect触发流水线执行并关闭它。(终端操作)
常用中间操作
过滤、切片、查找、匹配、映射和归约
filter,map,limit,sorted,distinct
中间操作 | 目 的 |
---|---|
filter | 过滤数据 |
distinct | 去重 |
skip | 跳过和limit相对 |
limit | |
map | 映射 |
sorted | 排序 |
常用终端操作
终端操作 | 目 的 |
---|---|
forEach | 消费流中的每个元素并对其应用 Lambda。这一操作返回 void |
count | 返回流中元素的个数。这一操作返回 long |
collect | 把流归约成一个集合,比如 List、Map 甚至是 Integer |
reduce | 计算 |
count | 数量 |
allMatch、anyMatch、noneMatch、findFirst和findAny 返回一个Optional
Optional类(java.util.Optional)是一个容器类,代表一个值存在或不存在。
分组 Collectors.groupingBy
// 根据类型分组
Map<Dish.Type, List<Dish>> dishesByType =
menu.stream().collect(groupingBy(Dish::getType));
// 根据属性复杂分组
public enum CaloricLevel { DIET, NORMAL, FAT }
@Test
public void fun16() {
Map<CaloricLevel, List<Dish>> dishesByCaloricLevel = menu.stream().collect(
Collectors.groupingBy(dish -> {
if (dish.getCalories() <= 400) return CaloricLevel.DIET;
else if (dish.getCalories() <= 700) return
CaloricLevel.NORMAL;
else return CaloricLevel.FAT;
}));
}
多级分组
@Test
public void fun17() {
Map<Dish.Type, Map<CaloricLevel, List<Dish>>> dishesByTypeCaloricLevel =
menu.stream().collect(
// 一级分类
Collectors.groupingBy(Dish::getType,
//二级分类
Collectors.groupingBy(dish -> {
if (dish.getCalories() <= 400) return CaloricLevel.DIET;
else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL;
else return CaloricLevel.FAT;
}))
);
}
分组求和(BigDecimal)
Map<String, BigDecimal> collect1 = list.stream().collect(Collectors.groupingBy(Detail::getCategoryName,
Collectors.reducing(BigDecimal.ZERO, Detail::getConsume, BigDecimal::add)));
Example
public class TransactionTest {
Trader raoul = new Trader("Raoul", "Cambridge");
Trader mario = new Trader("Mario", "Milan");
Trader alan = new Trader("Alan", "Cambridge");
Trader brian = new Trader("Brian", "Cambridge");
List<Trader> traders = Arrays.asList(raoul, mario, alan, brian);
List<Transaction> transactions = Arrays.asList(
new Transaction(brian, 2011, 300),
new Transaction(raoul, 2012, 1000),
new Transaction(raoul, 2011, 400),
new Transaction(mario, 2012, 710),
new Transaction(mario, 2012, 700),
new Transaction(alan, 2012, 950)
);
@Test
public void fun1() {
//找出2011年发生的所有交易,并按交易额排序(从低到高)
List<Transaction> collect = transactions.stream()
.filter(item -> item.getYear() == 2011)
.sorted(Comparator.comparingInt(Transaction::getValue))
.collect(Collectors.toList());
collect.forEach(System.out::println);
}
@Test
public void fun2() {
//交易员都在哪些不同的城市工作过
List<String> collect1 = transactions.stream().
map(i -> i.getTrader().getCity())
.distinct()
.collect(Collectors.toList());
collect1.forEach(System.out::println);
}
@Test
public void fun3() {
//查找所有来自于剑桥的交易员,并按姓名排序
List<Trader> cambridge = traders.stream().filter(i -> i.getCity().equals("Cambridge"))
.distinct()
.sorted(Comparator.comparing(Trader::getName))
.collect(Collectors.toList());
cambridge.forEach(System.out::println);
}
@Test
public void fun4() {
// 返回所有交易员的姓名字符串,按字母顺序排序
List<String> collect = traders.stream()
.sorted(Comparator.comparing(Trader::getName))
.map(Trader::getName)
.collect(Collectors.toList());
collect.forEach(System.out::println);
}
@Test
public void fun5() {
// 有没有交易员是在米兰工作的
boolean milan = traders.stream()
.anyMatch(i -> i.getCity().equals("Milan"));
System.out.println(milan);
}
@Test
public void fun6() {
// 打印生活在剑桥的交易员的所有交易额
transactions.stream()
.filter(i -> "Cambridge".equals(i.getTrader().getCity()))
.map(Transaction::getValue)
.forEach(System.out::println);
}
@Test
public void fun7() {
// 所有交易中,最高的交易额是多少
Optional<Integer> reduce = transactions.stream()
.map(Transaction::getValue)
.reduce(Integer::max);
System.out.println(reduce.get());
}
@Test
public void fun8() {
// 找到交易额最小的交易
Optional<Transaction> reduce = transactions.stream()
.reduce((t1, t2) -> t1.getValue() < t2.getValue() ? t1 : t2);
System.out.println(reduce.get());
Optional<Transaction> min = transactions.stream()
.min(Comparator.comparing(Transaction::getValue));
System.out.println(min);
}
}