为什么可以进行流式变成,例如 .filter .findFirst .map 等操作 ?
我们可以看一下 Stream 接口方法定义
1、Stream中常用操作方法
操作方法也分为 中间方法 和 终端方法
- 中间方法:调用方法后返回的依然为 Stream
- 终端方法: 调用方法后返回的不为 Stream 及 Stream子类
过滤筛选:filter 排序:sorted 去重:distinct 映射:map 查找匹配(终端操作):anyMatch、allMatch、noneMatch、findFirst、findAny 截短流:limit 跳过元素:ship 流的扁平化:flatMap 可以将生成的单个流合并起来,即扁平化一个流。 循环(终端操作):forEach 收集器(终端操作):collection 最大值(终端操作) : max min
代码案例
public class Trader {
/**
* 交易员名字
*/
private final String name;
/**
* 所在城市
*/
private final String city;
public Trader(String n, String c) {
this.name = n;
this.city = c;
}
public String getCity() {
return city;
}
public String getName() {
return name;
}
public String toString(){
return "{"+"Trader:"+this.name+"in " + this.city;
}
}
// 交易信息类
public class Transaction {
/**
* 交易员信息
*/
private final Trader trader;
/**
* 年
*/
private final int year;
/**
* 交易金额
*/
private final int value;
public Transaction(Trader trader, int year, int value){
this.value = value;
this.year = year;
this.trader = trader;
}
public Trader getTrader(){
return this.trader;
}
public int getValue() {
return value;
}
public int getYear() {
return year;
}
public String toString(){
return "{"+this.trader+","+"year:"+this.year+","+"value:"+this.value+"}";
}
}
public class java8Function {
/**
* 1)过滤筛选:filter
*
* stream 接口支持filter方法,该操作接收一个谓词Predicate(一个返回bollean的函数)作为参数,并返回一个所有符合谓词元素的流。
*
* 2)排序:sort
*
* 3)去重:distinct
*
* 4)映射:map
*
* map方法,它会接收一个函数作为参数,这个函数会被应用到每个元素上,并将其映射成一个新的元素。
*
* 5)查找匹配:anyMatch、allMatch、noneMatch、findFirst、findAny
*
* anyMatch:流中是否有一个元素能匹配给定的谓词。
*
* allMath:流中所有元素是否能匹配给定的谓词。
*
* noneMath:可以确保流中没有任何元素与给定的谓词匹配。
*
* findAny:返回当前流中的任意元素。
*
* findFirst:返回流中的第一个元素。
*
* findAny 和 findFirst 有什么区别?
*
* 答案是并行,找到一个元素在并行上限制有很多,如果不关心返回的那个元素,请使用findAny,因为它在使用并行流时限制很少。
*
* 6)归约和汇总:reduce、groupingBy
*
* reduce:接收两个参数,归约函数
*
* 1)一个初始值,
*
* 2)一个 BinaryOperator<T> 来将两个元素结合起来产生一个新值,
*
* 求和用lambda (a,b) ->a+b
*
* 求积用lambda (a,b) ->a*b
*
* groupingBy:对流按照元素进行分组
*
* Map<Currency,List<Transaction>> transactionByCurrencies =
*
* transactions.stream().collect(groupingBy(Transaction::getCurrency));
*
* 7)截短流
*
* 流支持limit(n),该方法返回一个不超过给定长度的流,所需长度作为常数传递给limit。如果流是有序的,则最多返回前n个元素。请注意,limit也可以用在无序流上,比如源是一个set,这种情况,limit的结果不会以任何顺序排列。
*
* 8)跳过元素
*
* 流支持ship(n)方法,返回一个扔掉前n个元素的流,如果流中元素不足n个,怎返回一个空流,注意 limit 和 ship 是互补的。
*
* 9)流的扁平化
*
* flatMap方法,可以将生成的单个流合并起来,即扁平化一个流。
*/
/**
* 测试用例:执行交易的交易员。八个查询案例
* 1)找出2011年发生的所有交易,并且按照交易额排序(从低到高)
* 2)交易员都在哪些不同城市工作过
* 3)查找所有来自于剑桥的交易员,并且按照姓名排序
* 4)返回所有交易员的姓名字符串,按字母排序
* 5)有没有交易员是在米兰工作过?
* 6)打印生活在剑桥的交易员所有交易额。
* 7)所有交易中,最高的交易额是多少?
* 8)找到交易额的最小的交易。
* */
public static void main(String arg[]){
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<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)
);
//1)找出2011年发生的所有交易,并且按照交易额排序(从低到高)
List<Transaction> tr2011 = transactions.stream()
.filter(transaction ->transaction.getYear() == 2011)
.sorted(Comparator.comparing(Transaction::getValue))
.collect(toList());
//2)交易员都在哪些不同城市工作过
List<String> cities = transactions.stream()
.map(transaction -> transaction.getTrader().getCity())
.distinct()
.collect(toList());
//3)查找所有来自于剑桥的交易员,并且按照姓名排序
List<Trader> name = transactions.stream()
.map(transaction -> transaction.getTrader())
.filter(trader -> trader.getCity().equals("Cambridge"))
.distinct()
.sorted(Comparator.comparing(Trader::getName))
.collect(toList());
//4)返回所有交易员的姓名字符串,按字母排序
String traderStr = transactions.stream()
.map(transaction -> transaction.getTrader().getName())
.distinct()
.sorted()
.reduce("",(n1,n2) -> n1+n2);
String traderStr2 = transactions.stream()
.map(transaction -> transaction.getTrader().getName())
.distinct()
.sorted()
.collect(joining());
//5)有没有交易员是在米兰工作过?
boolean mailanBased = transactions.stream()
.anyMatch(transaction -> transaction.getTrader().getCity().equals("Milan"));
//6)打印生活在剑桥的交易员所有交易额。
transactions.stream()
.filter(transaction -> transaction.getTrader().getCity().equals("Cambridge"))
.map(Transaction::getValue)
.forEach(System.out::println);
//7)所有交易中,最高的交易额是多少?
Optional<Integer> highestValue = transactions.stream()
.map(transaction -> transaction.getValue())
.reduce(Integer::max);
//8)找到交易额的最小的交易。
Optional<Transaction> smallestTransaction = transactions.stream()
.min(Comparator.comparing(Transaction::getValue));
}
}
2、容易掉入的坑
- lambda 表达式中虽然限制了 所应用的变量为 final类型,但是也可能由于使用不规范,导致数据不安全的场景。
- 对于lambda 表达式 返回的 Optional 尽量进行非空判定,否则直接 get() 可能会导致空指针异常。