引例:

         List<String> strList = Arrays.asList("zhaojigang","nana","tianya","nana");
Stream<String> streamList = strList.stream();//集合转为stream
strList = streamList.distinct().filter(str->!str.equals("tianya")).sorted(String::compareTo).collect(Collectors.toList());
strList.forEach(System.out::println);

说明:

  • 第一行:创建数组并转为List
  • 第二行:根据List创建stream
  • 第三行:对该stream进行去重-->选择-->排序-->stream转为List
  • 第四行:遍历该List

以上代码显示了stream API的方便。当然,上边的代码可以更为简洁,如下改为一行:

Arrays.asList("zhaojigang","nana","tianya","nana").stream().distinct().filter(str->!str.equals("tianya")).sorted(String::compareTo).collect(Collectors.toList()).forEach(System.out::println);

以上代码有一个易错点:filter是选择而不是过滤,即filter是选择满足条件的元素

一、创建Stream

三种常用API:

  • 集合-->Stream:stream()
  • 数组-->Stream:Stream.of(T t)或者Arrays.stream(T[] t)
  • 任意元素-->Stream:Stream.of(T... values)
         List<String> strList = Arrays.asList("zhaojigang","nana","tianya","nana");
Stream<String> streamList = strList.stream();//集合转为stream String[] strArray = {"java","c++","c"};
Stream<String> streamArray = Stream.of(strArray);//数组转为Stream
Stream<String> streamArray2 = Arrays.stream(strArray);//数组转为Stream Stream<String> streamPartArray = Arrays.stream(strArray, 0, 2);//转换部分数组,范围:[0,2) Stream<String> streamSelf = Stream.of("python","basic","php");//任意元素

还有一种:用于产生无限流的,Stream.generate(Supplier<T> s)。

二、Stream 2 array/collection/String/map

1、stream2array

         Stream<String> strStream = Stream.of("java","c++","c","python");
Object[] objectArray = strStream.toArray();//只能返回Object[]
String[] strArray = strStream.toArray(String[]::new);//构造器引用(类似于方法引用),可以返回String[]

说明:

通过构造器引用(类似于方法引用),可以构造出具体类型的数组。

2、stream2collection

         List<String> strList = strStream.collect(Collectors.toList());//返回List
Set<String> strSet = strStream.collect(Collectors.toSet());//返回set
ArrayList<String> strArrayList = strStream.collect(Collectors.toCollection(ArrayList::new));//收集到指定的List集合,例如收集到ArrayList

说明:

通过构造器引用,可以构造出具体类型的集合。

3、将stream中的元素拼接起来(joining()、joining(","))

         Stream<String> strStream = Stream.of("java","c++","c","python");
String str = strStream.collect(Collectors.joining());//将所有字符串拼接起来,结果:javac++cpython
System.out.println(str); String str2 = strStream.collect(Collectors.joining(","));//将所有字符串拼接起来,中间用","隔开,结果:java,c++,c,python
System.out.println(str2);

4、stream2map(toMap、toConcurrentMap)

         Stream<String> strStream = Stream.of("java","c++","c","python");
Map<String, Integer> map1 = strStream.collect(Collectors.toMap(Function.identity(), (x)->0));
//Function.identity()-->返回strStream中的元素,toMap方法的我两个参数都是Function接口型的,所以第二个参数即使只放0,也不能直接写作0,可以使用如上的方式进行操作 for(String key : map1.keySet()){
System.out.println("key:"+key+"->"+"value:"+map1.get(key));
}
//结果
/*
key:python->value:0
key:c++->value:0
key:c->value:0
key:java->value:0
*/

说明:

  • toMap-->stream转为map
  • Function.identity()-->返回stream中的元素

如果key重复的话,这时就会出现问题"duplicate key",采用如下方式解决(增加第三个参数):

         Stream<String> strStream = Stream.of("java","c++","c","python","java");
Map<String, Integer> map1 = strStream.collect(Collectors.toMap(Function.identity(), //key
(x)->0, //value
(existingValue, newValue) -> existingValue));//如果key重复,取旧值

需要指定返回map的具体类型(增加第四个参数)。

         Map<String, Integer> map1 = strStream.collect(Collectors.toMap(Function.identity(), //key
(x)->0, //value
(existingValue, newValue) -> existingValue,//如果key重复,取旧值
TreeMap::new));//返回TreeMap

注意:每一个toMap就会对应一个相应的toConcurrentMap

5、groupingBy partitioningBy

         /***************************groupingBy partitioningBy**************************/
Stream<Locale> localeStream = Stream.of(Locale.getAvailableLocales());
Map<String, List<Locale>> country2localeList = localeStream.collect(Collectors.groupingBy(Locale::getCountry));//根据国家分组,groupBy的参数是分类器
List<Locale> locales = country2localeList.get("CH"); Map<String, Set<Locale>> country2localeSet = localeStream.collect(Collectors.groupingBy(Locale::getCountry, Collectors.toSet()));//根据国家分组,groupBy的参数是分类器,返回set
Set<Locale> localeSet = country2localeSet.get("CH"); Map<Boolean, List<Locale>> country2locales = localeStream.collect(Collectors.partitioningBy(locale->locale.getLanguage().equals("en")));//分成两组,一组为true(即语言是en的),一组为false(即语言不是en的)
List<Locale> trueLocale = country2locales.get(true);

三、filter(Predicate p)

注意:是选择而非过滤

         Stream<String> streamSelf = Stream.of("python","basic","php");
streamSelf.filter(str->str.startsWith("p")).forEach(System.out::println);

注意:

  • stream也是可以foreach的,没必要一定要转化成集合再foreach

更好的写法可能是下边这种:

         Predicate<String> startCondition = str->str.startsWith("p");
streamSelf.filter(startCondition).forEach(System.out::println);

说明:将条件(通常是lambda表达式)抽取出来。这种方式在多个条件的情况下比较清晰。

注意:函数式接口 = lambda表达式 (即lambda表达式只能返回为函数式接口)

         Stream<String> s = Stream.of("java1","java3","java","php12");
Predicate<String> condition1 = str->str.length()==5;//条件1
Predicate<String> condition2 = str->str.startsWith("j");//条件2
s.filter(condition1.and(condition2)).forEach(System.out::println);//and条件

说明:

多条件运算:and or

四、map(Function mapper)

作用:对流中的每一个元素进行操作。

         Stream<String> streamSelf = Stream.of("python","basic","php");
streamSelf.map(String::toUpperCase).forEach(System.out::println);

说明:将流内的每一个String全部转换为了大写。

五、reduce 

作用:对stream中的每一个元素做聚合操作。

1         Stream<Integer> reduceStream = Stream.of(1,2,3,4,5);
2 Optional<Integer> sumOption = reduceStream.reduce((x,y)->x+y);//计算1+2+3+4+5,即对元素中的元素进行聚合计算,而map是对元素中的每一个元素分别计算(注意:如果stream为null的话,就会产生无效的结果,需要使用Optional接收)
3 //Optional<Integer> sumOption = reduceStream.reduce(Integer::sum);//计算1+2+3+4+5,即对元素中的元素进行聚合计算,而map是对元素中的每一个元素分别计算
4
5 Integer result = reduceStream.reduce(0, Integer::sum);//0为标识值,即计算:0+1+2+。。+5,如果整个stream为null,就返回标识值。
6 System.out.println(result);

注意:以上是reduce的简单形式,即内联函数是(T,T)->T,即返回值和参数类型是一样的,返回值和参数类型不同的场景需要自己编写函数(用的较少)

六、Optional

两种用法:

  • ifPresent(xxx):存在的就执行xxx,不存在就什么都不执行
  • orElse(xxx):存在就返回存在的值,不存在就返回xxx(可以理解为是默认值)
1         Stream<String> optionalStream = Stream.of("java","python","basic");
2 Optional<String> optionValue = optionalStream.filter(str->str.startsWith("p")).findFirst();
3 optionValue.ifPresent(str->System.out.println(str));//if optionalValue为true,即str存在,则输出str,当然也可以使用如下
4 String str = optionValue.orElse("xxx");//如果optionValue为false,即不存在以p开头的字符串时,使用"xxx"来替代
5 System.out.println(str);

七、limit skip contact

1、limit(long size)

作用:截取stream的前size个元素。

         Stream<String> streamSelf = Stream.of("python","basic","php");
streamSelf.limit(2).forEach(System.out::println);//截取前两个

2、skip(long size)

作用:跳过stream的钱size个元素

         Stream<String> streamSelf = Stream.of("python","basic","php");
streamSelf.skip(2).forEach(System.out::println);//跳过前两个

3、contact(Stream<T>,Stream<T>)

作用:拼接两个stream

         Stream<String> streamSelf = Stream.of("python","basic","php");
Stream<String> streamSelf2 = Stream.of("python2","basic2","php2");
Stream.concat(streamSelf, streamSelf2).forEach(System.out::println);

八、聚合函数 count max min findFirst findAny anyMatch allMatch noneMatch

         Stream<String> streamSelf = Stream.of("python","basic","php","b");
System.out.println(streamSelf.count());//计算流中的元素个数
Optional<String> largest = streamSelf.max(String::compareToIgnoreCase);//寻找最大值
if(largest.isPresent()){
System.out.println(largest.get());
}

说明:min函数也一样。

注意:Optional的使用,上边的是最差的一种形式,见"六"。

         Optional<String> firstMatch = streamSelf.filter(str->str.startsWith("b")).findFirst();//寻找第一个符合条件的元素
firstMatch.ifPresent(System.out::println);//这是Optional的第一种用法 Optional<String> anyMatch = streamSelf.parallel().filter(str->str.startsWith("b")).findAny();//返回集合中符合条件的任意一个元素,对于并行处理非常好(因为多个线程只要有一个线程找到了,整个计算就会结束)
if(anyMatch.isPresent()){
System.out.println(anyMatch.get());//这里的结果可能是b,有可能是basic
} boolean isAnyMatch = streamSelf.parallel().anyMatch(str->str.startsWith("c"));//集合中是否有一个满足条件
System.out.println(isAnyMatch); Stream<String> streamSelf3 = Stream.of("basic","b");
boolean isAllMatch = streamSelf3.parallel().allMatch(str->str.startsWith("b"));//集合中是否所有元素都满足条件
System.out.println(isAllMatch); boolean isAllNotMatch = streamSelf.parallel().noneMatch(str->str.startsWith("p"));//集合中是否没有一个元素满足条件
System.out.println(isAllNotMatch);

注意:

  • optional的最佳用法:ifPresent()-->如果有就输出,如果没有,什么都不做
  • parallel():将stream转为并行流,并行流的使用一定要注意线程安全

九、原始类型流

  • IntStream:int、short、char、byte、boolean
  • LongStream:long
  • DoubleStream:double、float

1.2 Stream API的更多相关文章

  1. Java 8 Stream API详解--转

    原文地址:http://blog.csdn.net/chszs/article/details/47038607 Java 8 Stream API详解 一.Stream API介绍 Java8引入了 ...

  2. Atitit 实现java的linq 以及与stream api的比较

    Atitit 实现java的linq 以及与stream api的比较 1.1. Linq 和stream api的关系,以及主要优缺点1 1.2. Linq 与stream api的适用场景1 1. ...

  3. Java 使用 Stream API 筛选 List

    前言 上课的时候看到老师用迭代器来遍历 List 中的元素的时候,我的内心是极其嫌弃的,这种迭代方法不能直接访问当前的元素,而且写起来也麻烦.于是上网查了查 Java 有没有类似于 Linq 的东西, ...

  4. Upgrading to Java 8——第四章 The Stream API

    在这章中我们将学习Stream API,在JDK 8 中的一项新的特性.为了理解这一章的主题,你需要知道如何使用Lambda表达式和java.util.function里的预定义的函数式接口. 一个S ...

  5. Java 8: Lambdas和新的集合Stream API

    Lambda是Java8的主要特色,Java 8: Lambdas & Java Collections | zeroturnaround.com一文介绍了使用Lambda集合处理大量数据的方 ...

  6. Java 8 Stream API Example Tutorial

    Stream API Overview Before we look into Java 8 Stream API Examples, let’s see why it was required. S ...

  7. 第二章 Stream API

    引例: 1 List<String> strList = Arrays.asList("zhaojigang","nana","tiany ...

  8. Java Stream API入门篇

    本文github地址 你可能还没意识到Java对函数式编程的重视程度,看看Java 8加入函数式编程扩充多少类就清楚了.Java 8之所以费这么大功夫引入函数式编程,原因有二: 代码简洁,函数式编程写 ...

  9. Java Stream API性能测试

    已经对Stream API的用法鼓吹够多了,用起简洁直观,但性能到底怎么样呢?会不会有很高的性能损失?本节我们对Stream API的性能一探究竟. 为保证测试结果真实可信,我们将JVM运行在-ser ...

  10. Java 8新特性:新语法方法引用和Lambda表达式及全新的Stream API

    新语法 方法引用Method references Lambda语法 Lambda语法在AndroidStudio中报错 Stream API 我正参加2016CSDN博客之星的比赛 希望您能投下宝贵 ...

随机推荐

  1. flask的orm框架(SQLAlchemy)-一对多查询以及多对多查询

    一对多,多对多是什么? 一对多.例如,班级与学生,一个班级对应多个学生,或者多个学生对应一个班级. 多对多.例如,学生与课程,可以有多个学生修同一门课,同时,一门课也有很多学生. 一对多查询 如果一个 ...

  2. NBUT1457

    不知道哪里的oj..做了交不上去.. 也是莫队的模板题 #include<iostream> #include<cstring> #include<cstdio> ...

  3. python接口自动化测试九:重定向相关

    allow_redirects=False  不重定向 # 获取重定向后的地址 loc = r.headers # 相对地址 host = 'https://i.cnblogs.com/' url = ...

  4. this和判断的位置对赋值的要求

    package charter01; public class Person { private String name; private int age; public String getName ...

  5. Android strings.xml中定义字符串显示空格

    <string name="str">字 符 串</string> 其中   就表示空格.如果直接在里面键入空格,无论多少空格都只会显示一个. 用的XML转 ...

  6. hdu 1385 Floyd 输出路径

    Floyd 输出路径 Sample Input50 3 22 -1 43 0 5 -1 -122 5 0 9 20-1 -1 9 0 44 -1 20 4 05 17 8 3 1 //收费1 3 // ...

  7. springbank 开发日志 SpringMVC是如何找到handler找到对应的方法并执行的

    从DispatcherServlet说起,本文讨论的内容都是DispatcherServlet的doDispatch方法完成 mappedHandler是一个HandlerExecutionChain ...

  8. P1219 八皇后 含优化 1/5

    题目描述 检查一个如下的6 x 6的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行.每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子. 上面的布局可以用序列2 4 6 1 3 ...

  9. Rstudio+mysql写入中文表

    1.在mysql中输入sql语句,新建一个支持中文的数据库 create database Chinadaydata DEFAULT CHARACTER SET gbk COLLATE gbk_chi ...

  10. 微信小程序 --- 表单输入验证(手机号、邮箱验证、输入非空)

    js代码 Page({                   /**    * 页面的初始数据    */         data: {         indicatorDots: false,   ...