java8 Stream 史上最全总结

温馨提醒:在电脑上看更方便

(一)stream的特点

一、 流操作都支持 lambda 表达式作为参数 ,函数式编程,充分利用了pipeline 思想

二、无修改 ,无储存

对原始数据无修改,对流和流的中间结果无储存

三 、 惰性执行

四、可以并发执行 , paralleStream

五、 默认只消费一次

1) 巧妙避免代码重复的方式 Supplier

 
  1. Supplier<Stream<String>> streamSupplier = () -> Stream.of("1", "2").filter(t -> t.equals("1"));

  2. final Optional<String> any = streamSupplier.get().findAny();//1

  3. final Optional<String> first = streamSupplier.get().findFirst();//2

六、Map 不支持 stream 流

(二)函数接口简介

1)一元函数式接口

接口 参数 返回类型 描述
Predicate T boolean 断言型接口
Consumer T void 消费型接口
Function T R 函数式接口
Supplier None T 供给型接口

2) 二元函数接口

接口 参数 返回类型 描述
BiFunction T, U R Function的变体
BiConsumer T, U void Consumer的变体
BiPredicate T, U boolean Predicate的变体

BiConsumer

 
  1. final HashMap<Object, Object> objectObjectHashMap = Maps.newHashMap();

  2. final BiConsumer biConsumer = (k, v) -> {

  3. System.out.println(k);

  4. System.out.println(v);

  5. };

  6. objectObjectHashMap.forEach(biConsumer);

BiPredicate

 
  1. Path testPath = Paths.get("/Users/qiaozhy/data");

  2. //finding files containing 'items' in name

  3. final BiPredicate<Path, BasicFileAttributes> items = (path, basicFileAttributes) -> {

  4. File file = path.toFile();

  5. return !file.isDirectory() &&

  6. file.getName().contains("items");

  7. };

  8. Stream<Path> stream =

  9. Files.find(testPath, 100,items

  10. );

  11. stream.forEach(System.out::println);

3) 扩展的运算符

BinaryOperator 继承BiFunction

 

  1. BinaryOperator<Integer> add = (n1, n2) -> n1 + n2;

UnaryOperator 继承Function

 
  1. UnaryOperator<Integer> dda = x -> x + 1;

(三)stream的操作

一、 流的创建 (最终都是依赖底层的StreamSupport类来完成Stream创建)

1) Collection 和数组

Collection.stream()

Collection.parallelStream()

  •  
  •  
  •  
  •  
  •  
final Stream<String> stream = Arrays.asList("11", "22").stream();final ArrayList<String> list = Lists.newArrayList();list.add("33");final Stream<String> stream3 = list.stream();final Stream<String> stringStream2 = list.parallelStream();

2) BufferedReader

java.io.BufferedReader.lines()

  •  
  •  
  •  
  •  
  •  
  •  
File file = new File("/Users/qiaozhy/data/qiao.txt");Reader reader  = new FileReader(file);BufferedReader bufferedReader = new BufferedReader(reader);final Stream<String> lines = bufferedReader.lines();final long count = lines.count();System.out.println(count);//2

 

3) 静态工厂

Arrays.stream(T array)

Stream.of()、iterate()、generate()

java.util.stream.IntStream.range()

java.nio.file.Files.list、find、walk等

Stream.builder()

 
  1. final IntStream intStream1 = Arrays.stream(new int[]{1, 2, 3});

  2.  

  3.  

  4. final Stream<String> stringStream = Stream.of("11", "22");

  5.  

  6. final Stream<Integer> iterate = Stream.iterate(5, t -> t + 1);

  7. iterate.limit(4).forEach(System.out::println);//5,6,7,8

  8.  

  9. //supplier 函数式接口的简化 (Math::random)

  10. Stream.generate(Math::random).limit(1).forEach(System.out::println);

  11. // 0.48158792725573907

  12.  

  13. final IntStream intStream = IntStream.range(1, 3);

  14.  

  15.  

  16. final Optional<Path> first = Files.walk(Paths.get("/Users/qiaozhy/data"))

  17. .peek(System.out::println).skip(2).findAny();

  18. first.orElseThrow(()-> new RuntimeException("结果为空"));

  19. System.out.println(first.get());//Users/qiaozhy/data/工作注意.txt

  20.  

  21. final Stream.Builder<Object> builder1 = Stream.builder();

  22. builder1.accept(66);

  23. builder1.add(2).add(3);

  24. builder1.build().forEach(System.out::println); // 66,2,3

4)其他

Pattern.splitAsStream(java.lang.CharSequence)

Random.ints()

JarFile.stream()

BitSet.stream()

 
  1. final Pattern pattern = Pattern.compile(",");

  2. final Stream<String> stringStream1 = pattern.splitAsStream("a,y,u");

  3. stringStream1.forEach(System.out::println);// a,y,u

  4.  

  5. Random random = new Random();

  6. final IntStream intStream2 = random.ints(1,20);

  7. intStream2.limit(2).forEach(System.out::println); // 5,18

  8.  

  9. JarFile jarFile = new JarFile("/Users/qiaozhy/.m2/javacc-5.0.jar");

  10. final Stream<JarEntry> stream1 = jarFile.stream();

  11. stream1.limit(1).forEach(System.out::println); //META-INF/

  12.  

  13. BitSet bitSet = new BitSet();

  14. bitSet.set(1);

  15. bitSet.set(45);

  16. final IntStream stream2 = bitSet.stream();

  17. stream2.forEach(System.out::println); // 1,45

二、 中间操作

无状态(Stateless)操作:每个数据的处理是独立的,不会影响或依赖之前的数据。如

filter()flatMap()flatMapToDouble()flatMapToInt()flatMapToLong()map()mapToDouble()mapToInt()mapToLong()peek()unordered()

unordered操作不会进行任何显式的打乱流的操作。它的工作是:消除流中必须保持的有序约束,因此允许之后的操作使用 不必考虑有序的优化

有状态(Stateful)操作:处理时会记录状态,比如处理了几个。后面元素的处理会依赖前面记录的状态,或者拿到所有元素才能继续下去。如

distinct()sorted()sorted(comparator)limit()skip()

 
  1. String [] arr = {"a","b","ed","c"};

  2. final List<String> collect = Arrays.stream(arr).sorted(Comparator.comparing(String::length)).collect(Collectors.toList());

  3. System.out.println(collect);//[a, b, c, ed]

  4. final List<String> collect1 = Arrays.stream(arr).sorted(Comparator.reverseOrder()).collect(Collectors.toList());

  5. System.out.println(collect1);//[ed, c, b, a]

  6. final Optional<String> any = Arrays.stream(arr).distinct().skip(1).limit(1).findAny();

  7. any.orElseThrow(()-> new RuntimeException("结果为空"));

  8. final String s = any.get();

  9. System.out.println(s);//b

 
  1. String[] words = new String[]{"Hello","World"};

  2. Arrays.stream(words)

  3. .map(word -> word.split(""))

  4. .flatMap(Arrays::stream)

  5. .forEach(System.out::print);

  6. //HelloWorld

  7. List<String> first= Arrays.asList("one", "two", "three", "four");

  8. List<String> second= Arrays.asList("A", "B", "C", "D");

  9. Stream.of(first,second).flatMap(Collection::stream).forEach(System.out::print);//onetwothreefourABCD

 
  1. Stream.of(1.0,2.0,3.0).mapToInt(Double::intValue).mapToObj(i->"a"+i).forEach(System.out::print);

三、终止操作

非短路操作:处理完所有数据才能得到结果。如

collect()count()forEach()forEachOrdered()max()min()reduce()toArray()等。

短路(short-circuiting)操作:拿到符合预期的结果就会停下来,不一定会处理完所有数据。如

anyMatch()allMatch()noneMatch()findFirst()findAny()

 
  1. List<String> strs = Arrays.asList("a", "a", "a", "a", "b");

  2. boolean aa = strs.stream().anyMatch(str -> str.equals("a"));

  3. System.out.println(aa);//true

  4. boolean bb = strs.stream().allMatch(str -> str.equals("a"));

  5. System.out.println(bb);//false

  6. boolean cc = strs.stream().noneMatch(str -> str.equals("a"));

  7. System.out.println(cc);//false

 
  1. String [] arr = {"a","b","ed","c"};

  2. final Optional<String> reduce = Arrays.stream(arr).reduce((a, b) -> a + b);

  3. reduce.orElseThrow(()-> new RuntimeException("结果为空"));

  4. System.out.println(reduce.get());//abedc

  5.  

  6. List<Integer> numList = Arrays.asList(1,2,3,4,5);

  7. int result = numList.stream().reduce(0,(a,b) -> a + b );

  8. System.out.println(result);

  9.  

  10. List<Integer> numList1 = Arrays.asList(1, 2, 3, 4, 5, 6);

  11. ArrayList<String> result1 = numList1.stream().reduce(new ArrayList<String>(),

  12. (a, b) -> {

  13. a.add("element-" + Integer.toString(b));

  14. return a;

  15. }, (a, b) -> null);

  16. System.out.println(result1);

  17. /*

  18. 需要注意的是这个reduce的签名还包含第三个参数,一个BinaryOperator<U>类型的表达式。

  19. 在常规情况下我们可以忽略这个参数,敷衍了事的随便指定一个表达式即可,目的是为了通过编译器的检查,

  20. 因为在常规的stream中它并不会被执行到,然而, 虽然此表达式形同虚设,可是我们也不是把它设置为null,

  21. 否者还是会报错。 在并行stream中,此表达式则会被执行到,在这里我们不进行讲解,因为我自己也没用过

  22. */

 
  1. Supplier<Stream<String>> streamSupplier = () -> Stream.of("a","d","b");

  2. //输出的顺序与元素的顺序严格一致

  3. streamSupplier.get().parallel().forEachOrdered(System.out::println);//a,d,b

  4. //主要的区别在并行流的处理上

  5. //输出的顺序不一定(效率更高)

  6. streamSupplier.get().parallel().forEach(System.out::println); // d,a,b

  7.  

  8. final String[] strings = streamSupplier.get().toArray(String[]::new);

  9. System.out.println(Arrays.toString(strings));//[a, d, b]

 
  1. final ArrayList<String> list = Lists.newArrayList();

  2. list.add("12");

  3. list.add("111");

  4. final List<String> collect = list.stream().collect(Collectors.toList());

  5. final Set<String> collect1 = list.stream().collect(Collectors.toSet());

  6. final Map<Integer, String> collect2 = list.stream().collect(Collectors.toMap(String::length, String::valueOf));

  7.  

  8. final Long lo = list.stream().collect(Collectors.counting());

  9.  

  10. final IntSummaryStatistics intSummaryStatistics = list.stream().collect(Collectors.summarizingInt(Integer::valueOf));

  11.  

  12. final String collect3 = list.stream().collect(Collectors.joining("--"));

  13.  

  14. final Optional<String> collect4 = list.stream().collect(Collectors.reducing((x, y) -> x + y));

  15.  

  16. final Map<Integer, List<String>> collect5 = list.stream().collect(Collectors.groupingBy(String::length));

  17.  

  18. final Optional<Integer> collect6 = list.stream().map(Integer::valueOf).collect(Collectors.maxBy(Integer::max));

(四 )、并行流

在创建Stream时,默认是创建串行流。但是可以使用parallelStream()来创建并行流或者parallel()将串行流转换成并行流。并行流也可以通过sequential()转换成串行流。

Java 8 Stream的并行流,本质上还是使用Fork/Join模型

(五)、特殊用法

 
  1. // map的循环方式

  2. final HashMap<Object, Object> objectObjectHashMap = Maps.newHashMap();

  3. objectObjectHashMap.put("1","2");

  4. objectObjectHashMap.put("5","77");

  5. objectObjectHashMap.forEach((a,b)->{

  6. System.out.println(a);

  7. System.out.println(b);

  8. });