StramApi常用操作

什么是流 ?

Stream 不是集合元素,它不是数据结构并不保存数据,它是有关算法和计算的,它更像一个高级版本的 Iterator。原始版本的 Iterator,用户只能显式地一个一个遍历元素并对其执行某些操作;高级版本的 Stream,用户只要给出需要对其包含的元素执行什么操作,比如 “过滤掉长度大于 10 的字符串”、“获取每个字符串的首字母”等,Stream 会隐式地在内部进行遍历,做出相应的数据转换。

Stream 就如同一个迭代器(Iterator),单向,不可往复,数据只能遍历一次,遍历过一次后即用尽了,就好比流水从面前流过,一去不复返.

流的结构

当我们使用一个流的时候,通常包括三个基本步骤:
获取一个数据源(source)→ 数据转换→执行操作获取想要的结果,每次转换原有 Stream 对象不改变,返回一个新的 Stream 对象(可以有多次转换),这就允许对其操作可以像链条一样排列,变成一个管道,如下图所示。

流管道 (Stream Pipeline) 的构成

生成 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()
流的操作类型分为两种:

Intermediate(中间):一个流可以后面跟随零个或多个 intermediate 操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用。这类操作都是惰性化的(lazy),就是说,仅仅调用到这类方法,并没有真正开始流的遍历。

Terminal(最终):一个流只能有一个 terminal 操作,当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作。Terminal 操作的执行,才会真正开始流的遍历,并且会生成一个结果,或者一个 side effect。
在对于一个 Stream 进行多次转换操作 (Intermediate 操作),每次都对 Stream 的每个元素进行转换,而且是执行多次,这样时间复杂度就是 N(转换次数)个 for 循环里把所有操作都做掉的总和吗?其实不是这样的,转换操作都是 lazy 的,多个转换操作只会在 Terminal 操作的时候融合起来,一次循环完成。我们可以这样简单的理解,Stream 里有个操作函数的集合,每次转换操作就是把转换函数放入这个集合中,在 Terminal 操作的时候循环 Stream 对应的集合,然后对每个元素执行所有的函数。

一个流操作的示例

int sum = widgets.stream()
.filter(w -> w.getColor() == RED).mapToInt(w -> w.getWeight()).sum();

stream() 获取当前小物件的 source,filter 和 mapToInt 为 intermediate 操作,进行数据筛选和转换,最后一个 sum() 为 terminal 操作,对符合条件的全部小物件作重量求和。

构造流的几种常见方法

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

1.流转换为其它数据结构

1.1 转为数组 Array
String[] arr=Stream.toArray(String[]::new)

代码:

private static  List<Person> getList() {List<Person> list = new ArrayList<>();list.add(new Person("范冰冰","女",28));list.add(new Person("刘亦菲","女",24));list.add(new Person("胡歌","男",30));return list;
}public static void main(String[] args) {List<Person> list = getList();//list 转 数组Person[] arr= list.stream().toArray(Person[]::new);Arrays.stream(arr).forEach(System.out::println);
}

效果:

1.2 转为集合 list,set Collection
List<String> list = stream.collect(Collectors.toList());
List<String> list = stream.collect(Collectors.toCollection(ArrayList::new));
Set set = stream.collect(Collectors.toSet());
Stack stack = stream.collect(Co`llectors.toColl`ection(Stack::new));

代码:

  public static void main(String[] args) {List<Person> list = getList();//list 转 数组Person[] arr= list.stream().toArray(Person[]::new);//数组 转 listList<Person> collect = Arrays.stream(arr).collect(Collectors.toList());
}
1.3 转为字符串
String str = stream.collect(Collectors.joining()).toString();
//Collectors.joining 收集器 支持灵活的参数配置,可以指定字符串连接时的 分隔符,前缀 和 后缀 字符串

代码:

final static String[] names = {"A", "B", "C", "D", "E"};
public static void main(String[] args) {String collect = Stream.of(names).collect(Collectors.joining("-", "{", "}"));System.out.println("字符串格式="+collect);
}

效果图:

2.流的操作

流的操作
接下来,当把一个数据结构包装成 Stream 后,就要开始对里面的元素进行各类操作了。常见的操作可以归类如下。
Intermediate:
map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered
Terminal:
forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator

常用操作:

map: 把 input Stream 的每一个元素,映射成 output Stream 的另外一个元素。

在项目中的应用:

1.list对象转换为某个属性的list字符串 (用来取list对象中的所有的对象的某个属性的list)

private static  List<Person> getList() {List<Person> list = new ArrayList<>();list.add(new Person("范冰冰","女",28));list.add(new Person("刘亦菲","女",24));list.add(new Person("胡歌","男",30));return list;}public static void main(String[] args) {//获取所有的学生名字List<Person> list = getList();List<String> resList = list.stream().map(Person::getName).collect(Collectors.toList());resList.stream().forEach(System.out::println);}


2.list对象转化为某两个属性拼接的list字符串

public static void main(String[] args) {//获取所有人  "名字+年龄" 格式 的listList<Person> list = getList();List<String> resList = list.stream().map(e -> e.getName()+"+"+e.getAge()).collect(Collectors.toList());resList.stream().forEach(System.out::println);}


3.list对象按照某个属性值进行分组

 private static  List<Person> getList() {List<Person> list = new ArrayList<>();list.add(new Person("范冰冰","女",28));list.add(new Person("刘亦菲","女",24));list.add(new Person("胡歌","男",30));list.add(new Person("胡歌","女",24));return list;}public static void main(String[] args) {//根据名字进行分组List<Person> list = getList();Map<Integer, List<Person>> collect = list.stream().collect(Collectors.groupingBy(Person::getAge));Set<Map.Entry<Integer, List<Person>>> entries = collect.entrySet();for(Map.Entry<Integer, List<Person>> entity:entries){System.out.println("key="+entity.getKey()+"value="+entity.getValue().size());}}


4.list对象按照某两个属性拼接进行分组

private static  List<Person> getList() {List<Person> list = new ArrayList<>();list.add(new Person("范冰冰","女",28));list.add(new Person("刘亦菲","女",24));list.add(new Person("胡歌","男",24));list.add(new Person("胡歌","女",24));return list;}public static void main(String[] args) {//根据 "性别-年龄" 格式进行分组List<Person> list = getList();Map<String, List<Person>> collect = list.stream().collect(Collectors.groupingBy(e -> e.getGender() + "-" + String.valueOf(e.getAge())));Set<Map.Entry<String, List<Person>>> entries = collect.entrySet();for(Map.Entry<String, List<Person>> entity:entries){System.out.println("key="+entity.getKey()+"  value="+entity.getValue().size());}}

StramApi常用操作相关推荐

  1. TensorFlow常用操作:代码示例

    1,定义矩阵代码示例: import tensorflow as tftf.zeros([3,4]) #定义3行4列元素均为0的矩阵tensor=tf.constant([1,2,3,4])#定义一维 ...

  2. Ubuntu 常用操作

    Ubuntu常用操作 外观操作 修改应用icon图标 终端美化 内存管理 内存查询 分区管理 日志清理 操作执行 自动执行多条命令 外观操作 修改应用icon图标 在/usr/share/applic ...

  3. IOS沙盒Files目录说明和常用操作

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launc ...

  4. 用Python轻松搞定Excel中的20个常用操作

    来源 |早起Python(ID: zaoqi-python) Excel与Python都是数据分析中常用的工具,本文将使用动态图(Excel)+代码(Python)的方式来演示这两种工具是如何实现数据 ...

  5. python和R对dataframe的常用操作的差异:head、tail、shape、dim、nrow、ncol、descirbe、summary、str

    python和R对dataframe的常用操作的差异:head.tail.shape.dim.nrow.ncol.descirbe.summary.str # python df.head() # R ...

  6. 【node】Sequelize常用操作、基本增删改查

    [node]Sequelize常用操作.基本增删改查 sequelize初始化 先初始化一个数据库实例 再初始化一个model实例 sequelize的数据类型 基本增删改查的写法 SELECT * ...

  7. JavaScript:对Object对象的一些常用操作总结

    JavaScript对Object对象的一些常用操作总结. 一.Object.assign() 1.可以用作对象的复制 var obj = { a: 1 }; var copy = Object.as ...

  8. ubuntu的学习教程(常用操作)

    摘要 最近在学习linux,把自己学习过程中遇到的常用操作以及一些有助于理解的内容记录下来.我主要用的是ubuntu系统 命令提示符 '~' 这个是指用户的家目录,用户分为root用户和普通用户,ro ...

  9. 20180929 VIM进入编辑模式、VIM命令模式常用操作

    2019独角兽企业重金招聘Python工程师标准>>> vim进入编辑模式方式 按键 作用 i 在当前字符前插入 I 在光标所在行的行首插入 a 在当前字符后插入 A 在光标所在行的 ...

最新文章

  1. 怎么把html4换文件夹打不开,HTML4
  2. matlab中 三种方法计算 Ax b,在MATLAB中,方程Ax=B的解可以用哪个命令求得? matlab 求助 解方程组...
  3. CSS Hack(Safari、Opera、Chrome、IE6、IE7、 IE8和IE9)
  4. C语言在linux终端下实现2048小游戏:第二版
  5. imp-00058: 遇到 oracle 错误 12560,MP-00058: 遇到 ORACLE 错
  6. 5双机配置_CentOS 7 高可用双机热备实现
  7. 关于eclipse中maven项目的问题
  8. [CGAL]建立一个正四面体
  9. 上古卷轴5:重制版Skyrim Together用MO无法替换游戏菜单Menu图像LOGO的问题解决
  10. Florian%C3%B3polis巴西北岸新业务的最佳场所四方数据分析
  11. 【纯净版windows系统】U盘启动制作图文教程
  12. Linux下 debug手段
  13. kb2919442不适用计算机,无法更新kb2919442,kb2919355,显示此更新不适用于你的计算机,求助...
  14. 阶跃信号的matlab,单位阶跃信号的表示-matlab
  15. CyberArticle(eLib电子图书馆)网文快捕
  16. Office 2013 中使用 MathType
  17. Django框架之入门介绍
  18. 边缘计算中的计算迁移概述
  19. IPCC summary
  20. 【论文阅读】CodeTrans: Towards Cracking the Language of Silicon‘s Code......

热门文章

  1. MySQL之undo log
  2. 2022-2028全球及中国自动车牌读取器行业研究及十四五规划分析报告
  3. INDEMIND 双目相机使用教程
  4. 把文件或者文件夹打包成jar
  5. Jackson线程安全问题
  6. EMR 系统集成公司信息化解决方案
  7. HTB-Responder
  8. 书评学习笔记《自动驾驶汽车环境感知》
  9. Hadoop学习——最大的敌人是自己
  10. Excel常用函数、逻辑函数(一)