java8-Stream

1、概览

但在当今这个数据大爆炸的时代,在数据来源多样化、数据海量化的今天,不少时候不得不脱离 RDBMS,或者以底层返回的数据为基础进行更上层的数据统计。而 Java 的集合 API 中,仅仅有极少许的辅助型方法,更多的时候是程序员须要用 Iterator 来遍历集合,完成相关的聚合应用逻辑。这是一种远不够高效、笨拙的方法。在 Java 7 中,若是要发现 type 为 grocery 的全部交易,而后返回以交易值降序排序好的交易 ID 集合,咱们须要这样写:html

List<Transaction> groceryTransactions = new Arraylist<>();
for(Transaction t: transactions){
 if(t.getType() == Transaction.GROCERY){
 groceryTransactions.add(t);
 }
}
Collections.sort(groceryTransactions, new Comparator(){
 public int compare(Transaction t1, Transaction t2){
 return t2.getValue().compareTo(t1.getValue());
 }
});
List<Integer> transactionIds = new ArrayList<>();
for(Transaction t: groceryTransactions){
 transactionsIds.add(t.getId());
}

可是若是是stream:java

List<Integer> transactionsIds = transactions.parallelStream().
 filter(t -> t.getType() == Transaction.GROCERY).
 sorted(comparing(Transaction::getValue).reversed()).
 map(Transaction::getId).
 collect(toList());

2、生成Stream的方式

有多种方式生成 Stream Source:程序员

  • 从 Collection 和数组:
    • Collection.stream()
    • Collection.parallelStream()
    • Arrays.stream(T array) or Stream.of()
    • 从 BufferedReader
    • java.io.BufferedReader.lines()
  • 静态工厂
    • java.util.stream.IntStream.range()
    • java.nio.file.Files.walk()
  • 本身构建
    • java.util.Spliterator
  • 其它
    • Random.ints()
    • BitSet.stream()
    • Pattern.splitAsStream(java.lang.CharSequence)
    • JarFile.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数据结构

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、转为其余数据结构

// 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();

4、流的操做

  • Intermediate:中间操做
    • map (mapToInt, flatMap 等) : 把元素映射成另外一个元素,好比把里面全部的元素都转成大写。
      List<String> output = wordList.stream().
      	map(String::toUpperCase).
      	collect(Collectors.toList());
- filter:过滤全部元素,接受一个返回boolean的表达式
	- distinct:去重
	- sorted:对 Stream 的排序经过 sorted 进行,它比数组的排序更强之处在于你能够首先对 Stream 进行各种 map、filter、limit、skip 甚至 distinct 来减小元素数量后,再排序,这能帮助程序明显缩短执行时间。
	sorted(Comparator<? super T> comparator);接受一个Comparator,
	
	如:sorted((p1, p2) -> p1.getName().compareTo(p2.getName()))
	- peek:  对每一个元素执行操做并返回一个新的 Stream, forEach有一样的功能,可是foreach是一个终端操做
	- limit、
	- skip:跳过前X个元素
	- parallel、
	- sequential、
	- unordered

- Terminal:终端操做
	- forEach : 接受一个表达式,对这个全部元素执行这个表达式
	forEachOrdere
	toArray
	- reduce:提供一个种子和一个表达式,从种子和全部元素依次执行这个表达式,每次执行的结果都是后一次表达式执行的种子。也能够没有种子,则会返回一个Optional。从这个意义上说,字符串拼接、数值的 sum、min、max、average 都是特殊的 reduce。例如 Stream 的 sum 就至关于:
	```java
// 字符串链接,concat = "ABCD"
String concat = Stream.of("A", "B", "C", "D").reduce("", String::concat); 
// 求最小值,minValue = -3.0
double minValue = Stream.of(-1.5, 1.0, -3.0, -2.0).reduce(Double.MAX_VALUE, Double::min); 
// 求和,sumValue = 10, 有起始值
int sumValue = Stream.of(1, 2, 3, 4).reduce(0, Integer::sum);
// 求和,sumValue = 10, 无起始值
sumValue = Stream.of(1, 2, 3, 4).reduce(Integer::sum).get();
// 过滤,字符串链接,concat = "ace"
concat = Stream.of("a", "B", "c", "D", "e", "F").
 filter(x -> x.compareTo("Z") > 0).
 reduce("", String::concat);
Integer sum = integers.reduce(0, Integer::sum);
- collect : java.util.stream.Collectors 类的主要做用就是辅助进行各种有用的 reduction 操做,

例如转变输出为 Collection : collect(Collectors.toList()); 把 Stream 元素进行归组 : groupingBy/partitioningBy。
- min:找到最小值
- max:找到最大值
- count
- anyMatch
- allMatch
- noneMatch
- findFirst
- findAny
- iterator
  • Short-circuiting:短路操做
    • anyMatch
    • allMatch
    • noneMatch
      • allMatch:Stream 中所有元素符合传入的 predicate,返回 true
      • anyMatch:Stream 中只要有一个元素符合传入的 predicate,返回 true
      • noneMatch:Stream 中没有一个元素符合传入的 predicate,返回 true
    • findFirst:返回第一个元素或者空,返回值是Optional !!!
    String optional = null;
        Optional.ofNullable(optional).ifPresent(String::toUpperCase); //由于这里是空值,因此直接跳过
        System.out.println("aa");  //这个程序只是打印了这个aa
- findAny: 返回流中的任意一个值
	- limit: 返回流中的前X个元素


# 5、Java8 parallelStream是线程不安全的!
	解决方案:
		https://www.cnblogs.com/puyangsky/p/7608741.html
		总结就是paralleStream里直接去修改变量是非线程安全的,可是采用collect和reduce操做就是知足线程安全的了(前提是不干扰源数据,而且与数据处理的顺序无关)。



# 6、CompletableFuture相关教程
	1. https://colobu.com/2016/02/29/Java-CompletableFuture/
	2. http://songkun.me/2018/05/27/2018-05-26-java8-completablefuture/
相关文章
相关标签/搜索