Java8新特性Stream API与Lambda表达式详解(2)

3 流与Lambda表达式的使用详解

简单说,对 Stream 的使用就是实现一个 filter-map-reduce 过程,产生一个最终结果,或者导致一个副作用(side effect)。

3.1流的构造

Stream在Java SE 8中非常重要,我们希望可以在JDK中尽可能广的使用Stream。我们为Collection提供了stream()和parallelStream(),以便把集合转化为流;此外数组可以通过Arrays.stream()被转化为流。

除此之外,Stream中还有一些静态工厂方法(以及相关的原始类型流实现),这些方法被用来创建流,例如Stream.of(),Stream.generate以及IntStream.range。其它的常用类型也提供了流相关的方法,例如String.chars,BufferedReader.lines,Pattern.splitAsStream,Random.ints和BitSet.stream。

下面提供最常见的几种构造 Stream 的样例。

 

// 构造流的几种常见方法
// 1. Individual values
Stream stream = Stream.of("a","b", "c");
// 2. Arrays
String [] strArray = new String[]{"a", "b", "c"};
stream = Stream.of(strArray);
stream = Arrays.stream(strArray);
// 3. Collections
List<String> list =Arrays.asList(strArray);
stream = list.stream();

需要注意的是,对于基本数值型,目前有三种对应的包装类型 Stream:

IntStream、LongStream、DoubleStream。当然我们也可以用 Stream<Integer>、Stream<Long> >、Stream<Double>,但是 boxing 和 unboxing 会很耗时,所以特别为这三种基本数值型提供了对应的 Stream。

Java8 中还没有提供其它数值型 Stream,因为这将导致扩增的内容较多。而常规的数值型聚合运算可以通过上面三种 Stream 进行。

// 数值流的构造
IntStream.of(new int[]{1, 2,3}).forEach(System.out::println);
IntStream.range(1,3).forEach(System.out::println);
IntStream.rangeClosed(1,3).forEach(System.out::println);

3.2流转换为其它数据结构

// 流转换为其它数据结构
// 1. Array
String[] strArray1 = stream.toArray(String[]::new);
// 2. Collection
List<String> list1 =stream.collect(Collectors.toList());
List<String> list2 =stream.collect(Collectors.toCollection(ArrayList::new));
Set set1 =stream.collect(Collectors.toSet());
Stack stack1 = stream.collect(Collectors.toCollection(Stack::new));
// 3. String
String str =stream.collect(Collectors.joining()).toString();

一个 Stream 只可以使用一次,上面的代码为了简洁而重复使用了数次。

3. 3 流的Intermediate操作

接下来,当把一个数据结构包装成 Stream 后,就要开始对里面的元素进行各类操作了。常见的操作可以归类如下。

·  Intermediate

map (mapToInt, flatMap ) filter distinct sorted peek limit skip parallel sequential unordered


map/flatMap

我们先来看 map。如果你熟悉 scala 这类函数式语言,对这个方法应该很了解,它的作用就是把 input Stream 的每一个元素,映射成 output Stream 的另外一个元素。

// 转换大写
List<String> output =wordList.stream().
map(String::toUpperCase).
collect(Collectors.toList());

下面看一个完整示例:

package lambda;

import java.util.Arrays;
import java.util.List;

public class MapAndReduceTest {
	// applying 12% VAT on each purchase
	// Without lambda expressions:
	List<Integer> costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);
	public void applying(){
		for (Integer cost : costBeforeTax) {
		      double price = cost + .12*cost;
		      System.out.print(price + " ");
		}
	}
	// Applying 12% VAT on each purchase
	// Old way:
	public void total(){
		double total = 0;
		for (Integer cost : costBeforeTax) {
		 double price = cost + .12*cost;
		 total = total + price;		 
		}
		System.out.println("Total : " + total);
	}
	
	// With Lambda expression:
	List<Integer> costBeforeTax2 = Arrays.asList(100, 200, 300, 400, 500);
	public void applying2(){
		costBeforeTax2.stream().map((cost) -> cost + .12*cost)
        .forEach(System.out::print);
	}
	public void total2(){
		//reduce() 是将集合中所有值结合进一个,Reduce类似SQL语句中的sum(), avg() 或count()
		double bill = costBeforeTax2.stream().map((cost) -> cost + .12*cost)
                .reduce((sum, cost) -> sum + cost)
                .get();
		System.out.println("Total : " + bill);
	}
	public static void main(String[] args) {
		MapAndReduceTest mr = new MapAndReduceTest();
		mr.applying();
		mr.total();
		System.out.println("=========================================");
		mr.applying2();
		mr.total2();
	}
}
/*Output:
112.0 224.0 336.0 448.0 560.0 Total : 1680.0
=========================================
112.0224.0336.0448.0560.0Total : 1680.0
 * */

// 平方数
List<Integer> nums =Arrays.asList(1, 2, 3, 4);
List<Integer> squareNums =nums.stream().
map(n -> n * n).
collect(Collectors.toList());

这段代码生成一个整数 list 的平方数 {1, 4, 9, 16}。<

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值