java8新特性系列之---Stream流式编程

一只会飞的鱼儿 1年前 ⋅ 1963 阅读
ad

为什么可以进行流式变成,例如 .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() 可能会导致空指针异常。

关于Webfunny

Webfunny专注于前端监控系统,前端埋点系统的研发。 致力于帮助开发者快速定位问题,帮助企业用数据驱动业务,实现业务数据的快速增长。支持H5/Web/PC前端、微信小程序、支付宝小程序、UniApp和Taro等跨平台框架。实时监控前端网页、前端数据分析、错误统计分析监控和BUG预警,第一时间报警,快速修复BUG!支持私有化部署,Docker容器化部署,可支持千万级PV的日活量!

  点赞 0   收藏 1
  • 一只会飞的鱼儿
    共发布53篇文章 获得8个收藏
全部评论: 0