首页 > 编程语言 >Java Stream学习笔记(一)

Java Stream学习笔记(一)

时间:2023-04-05 22:01:41浏览次数:38  
标签:Java Stream stream List 笔记 jkl userList strings

Java Stream学习笔记

Stream是Java 8 API添加的一个新的抽象,称为流Stream,以一种声明性方式处理数据集合(侧重对于源数据计算能力的封装,并且支持序列与并行两种操作方式)。

一、特点

1、代码简洁: 函数式编程写出的代码简洁且意图明确,使用stream接口让你从此告别for循环。

2、多核友好:Java函数式编程使得编写并行程序如此简单,就是调用一下方法。

二、流的操作

2.1.通过Stream创建
Stream<Integer> stream1 = Stream.of(1,2,3,4,5);
2.2.通过Collection集合创建(最常用的方式,重点掌握)
List<Integer> integerList = new ArrayList<>();
        integerList.add(1);
        integerList.add(2);
        integerList.add(3);
        integerList.add(4);
        integerList.add(5);
        Stream<Integer> listStream = integerList.stream();
2.3.通过数组创建
int[] intArr = {1, 2, 3, 4, 5};
        IntStream arrayStream = Arrays.stream(intArr);

通过Arrays.stream方法生成流,并且该方法生成的流是数值流【即IntStream】而不是 Stream

注:

使用数值流可以避免计算过程中拆箱装箱,提高性能。

Stream API提供了mapToInt、mapToDouble、mapToLong三种方式将对象流【即Stream 】转换成对应的数值流,同时提供了boxed方法将数值流转换为对象流

2.4.通过文件创建
try {
            Stream<String> fileStream = Files.lines(Paths.get("data.txt"), Charset.defaultCharset());
 } catch (IOException e) {
            e.printStackTrace();
	}

通过Files.line方法得到一个流,并且得到的每个流是给定文件中的一行
2.5.函数创建
iterator
Stream<Integer> iterateStream = Stream.iterate(0, n -> n + 2).limit(5);


iterate方法接受两个参数,第一个为初始化值,第二个为进行的函数操作,因为iterator生成的流为无限流,通过limit方法对流进行了截断,只生成5个偶数 

generator
Stream<Double> generateStream = Stream.generate(Math::random).limit(5);

generate方法接受一个参数,方法参数类型为Supplier ,由它为流提供值。generate生成的流也是无限流,因此通过limit对流进行了截断

三、操作符

流的操作符类型主要分为:中间操作符、终端操作符

中间操作符

通常对于Stream的中间操作,可以视为是源的查询,并且是懒惰式的设计,对于源数据进行的计算只有在需要时才会被执行,与数据库中视图的原理相似;

Stream流的强大之处便是在于提供了丰富的中间操作,相比集合或数组这类容器,极大的简化源数据的计算复杂度

一个流可以跟随零个或多个中间操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用

这类操作都是惰性化的,仅仅调用到这类方法,并没有真正开始流的遍历,真正的遍历需等到终端操作时,常见的中间操作有下面即将介绍的 filter、map 等

3.1.中间操作符流的方法

中间操作符方法一共提供 8种方法。

流方法 作用 示例
filter 通过设置的条件过滤出数据(Lambda) List strings = Arrays.asList(“abc”, “”, “bc”, “efg”, “abcd”,"", “jkl”);List filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
map 接受一个函数作为参数。这个函数会被应用到每个元素上,并将其映射成一个新的元素(使用映射一词,是因为它和转换类似,但其中的细微差别在于它是“创建一个新版本”而不是去“修改”) List strings = Arrays.asList(“abc”, “abc”, “bc”, “efg”, “abcd”,“jkl”, “jkl”);
List mapped = strings.stream().map(str->str+"-itcast").collect(Collectors.toList());
distinct d对数据流中的元素进行去重操作,要重写hashCode和equals方法(根据流所生成元素的hashCode和equals方法实现)的流 List numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
numbers.stream().filter(i -> i % 2 == 0).distinct().forEach(System.out::println);
sorted 返回排序后的流 Liststrings1=Arrays.asList(“abc”, “abd”, “aba”, “efg”, “abcd”,“jkl”, “jkl”);List sorted1 = strings1.stream().sorted().collect(Collectors.toList());
limit 会返回一个不超过给定长度的流(限制数据长度) List strings = Arrays.asList(“abc”, “abc”, “bc”, “efg”, “abcd”,“jkl”, “jkl”);List limited = strings.stream().limit(3).collect(Collectors.toList());
skip 返回一个扔掉了前n个元素的流(跳过n条数据) List strings = Arrays.asList(“abc”, “abc”, “bc”, “efg”, “abcd”,“jkl”, “jkl”);List skiped = strings.stream().skip(3).collect(Collectors.toList());
flatMap 使用flatMap方法的效果是,各个数组并不是分别映射成一个流,而是映射成流的内容。所有使用map(Arrays::stream)时生成的单个流都被合并起来,即扁平化为一个流 List strings = Arrays.asList(“abc”, “abc”, “bc”, “efg”, “abcd”,“jkl”, “jkl”);Stream flatMap = strings.stream().flatMap(Java8StreamTest::getCharacterByString);
peek 对元素进行遍历处理 List strings = Arrays.asList(“abc”, “abc”, “bc”, “efg”, “abcd”,“jkl”, “jkl”);strings .stream().peek(str-> str + "a").forEach(System.out::println);
终端操作符

Stream流执行完终端操作之后,无法再执行其他动作,否则会报状态异常,提示该流已经被执行操作或者被关闭,想要再次执行操作必须重新创建Stream流

一个流有且只能有一个终端操作,当这个操作执行后,流就被关闭了,无法再被操作,因此一个流只能被遍历一次,若想在遍历需要通过源数据在生成流。

终端操作的执行,才会真正开始流的遍历。如 count、collect 等

3.2终端操作符流的方法

终端操作符一共提供 12 种方法。

流方法 作用 示例
collect 收集器,将流转换为其他形式 List strings = Arrays.asList(“cv”, “abd”, “aba”, “efg”, “abcd”,“jkl”, “jkl”);Set set = strings.stream().collect(Collectors.toSet());List list = strings.stream().collect(Collectors.toList());Map<String, String> map = strings.stream().collect(Collectors.toMap(v ->v.concat("_name"), v1 -> v1, (v1, v2) -> v1));
forEach 遍历流 List strings = Arrays.asList(“cv”, “abd”, “aba”, “efg”, “abcd”,“jkl”, “jkl”);strings.stream().forEach(s -> out.println(s));
findFirst 返回第一个元素 List strings = Arrays.asList(“cv”, “abd”, “aba”, “efg”, “abcd”,“jkl”, “jkl”);
findAny 将返回当前流中的任意元素 List strings = Arrays.asList(“cv”, “abd”, “aba”, “efg”, “abcd”,“jkl”, “jkl”);
Optional any = strings.stream().findAny();
count 返回流中元素总数 List strings = Arrays.asList(“cv”, “abd”, “aba”, “efg”, “abcd”,“jkl”, “jkl”);
long count = strings.stream().count();
sum 求和 int sum = userList.stream().mapToInt(User::getId).sum();
max 最大值 int max = userList.stream().max(Comparator.comparingInt(User::getId)).get().getId();
min 最小值 int min = userList.stream().min(Comparator.comparingInt(User::getId)).get().getId();
anyMatch 检查是否至少匹配一个元素,返回boolean List strings = Arrays.asList(“abc”, “abd”, “aba”, “efg”, “abcd”,“jkl”, “jkl”);
boolean b = strings.stream().anyMatch(s -> s == “abc”);
noneMatch 检查是否没有匹配所有元素,返回boolean List strings = Arrays.asList(“abc”, “abd”, “aba”, “efg”, “abcd”,“jkl”, “jkl”);
boolean b = strings.stream().noneMatch(s -> s == “abc”);
reduce 可以将流中元素反复结合起来,得到一个值 List strings = Arrays.asList(“cv”, “abd”, “aba”, “efg”, “abcd”,“jkl”, “jkl”);Optional reduce = strings.stream().reduce((acc,item) -> {return acc+item;});if(reduce.isPresent())out.println(reduce.get());

四、Collect收集器(终端操作符)

Collector:结果收集策略的核心接口,具备将指定元素累加存放到结果容器中的能力;并在Collectors工具中提供了Collector接口的实现类

  • 示例数据
    public static void main(String[] args) {
        List<User> userList = getUserList();
    }
 
    private static List<User> getUserList() {
        List<User> userList = new ArrayList<>();
 
        userList.add(new User(1,"张三",18,"上海"));
        userList.add(new User(2,"王五",16,"上海"));
        userList.add(new User(3,"李四",20,"上海"));
        userList.add(new User(4,"张雷",22,"北京"));
        userList.add(new User(5,"张超",15,"深圳"));
        userList.add(new User(6,"李雷",24,"北京"));
        userList.add(new User(7,"王爷",21,"上海"));
        userList.add(new User(8,"张三丰",18,"广州"));
        userList.add(new User(9,"赵六",16,"广州"));
        userList.add(new User(10,"赵无极",26,"深圳"));
 
        return userList;
    }
4.1.1toList(常用)

将用户ID存放到List集合中

List<Integer> idList = userList.stream().map(User::getId).collect(Collectors.toList()) ;
4.2.toMap(常用)

将用户ID和Name以Key-Value形式存放到Map集合中

Map<Integer,String> userMap = userList.stream().collect(Collectors.toMap(User::getId,User::getName));
4.3.toSet(常用)

将用户所在城市存放到Set集合中

Set<String> citySet = userList.stream().map(User::getCity).collect(Collectors.toSet());
4.4.counting

符合条件的用户总数

long count = userList.stream().filter(user -> user.getId()>1).collect(Collectors.counting());
4.5.summingInt

对结果元素即用户ID求和

Integer sumInt = userList.stream().filter(user -> user.getId()>2).collect(Collectors.summingInt(User::getId)) ;
4.6.minBy

筛选元素中ID最小的用户

User maxId = userList.stream().collect(Collectors.minBy(Comparator.comparingInt(User::getId))).get() ;
4.7.joining

将用户所在城市,以指定分隔符链接成字符串;

String joinCity = userList.stream().map(User::getCity).collect(Collectors.joining("||"));
4.8.groupingBy (常用)

按条件分组,以城市对用户进行分组;

Map<String,List<User>> groupCity = userList.stream().collect(Collectors.groupingBy(User::getCity));

五、orElse 和orElseGet

5.1.orElse(null)

表示如果一个都没找到返回null(orElse()中可以塞默认值。如果找不到就会返回orElse中设置的默认值)

/**
 * Return the value if present, otherwise return {@code other}.
 *
 * @param other the value to be returned if there is no value present, may
 * be null
 * @return the value, if present, otherwise {@code other}
 * 返回值,如果存在,否则返回其他
 */
public T orElse(T other) {
    return value != null ? value : other;
}
5.2.orElseGet(null)

表示如果一个都没找到返回null(orElseGet()中可以塞默认值。如果找不到就会返回orElseGet中设置的默认值)

orElse() 接受类型T的 任何参数,而orElseGet()接受类型为Supplier的函数接口,该接口返回类型为T的对象

/**
 * Return the value if present, otherwise invoke {@code other} and return
 * the result of that invocation.
 *
 * @param other a {@code Supplier} whose result is returned if no value
 * is present
 * @return the value if present otherwise the result of {@code other.get()}
 * @throws NullPointerException if value is not present and {@code other} is
 * null
 * 返回值如果存在,否则调用其他值并返回该调用的结果
 */
public T orElseGet(Supplier<? extends T> other) {
    return value != null ? value : other.get();
}
5.3.orElse(null)和orElseGet(null)区别

1、当返回Optional的值是空值null时,无论orElse还是orElseGet都会执行

2、而当返回的Optional有值时,orElse会执行,而orElseGet不会执行

标签:Java,Stream,stream,List,笔记,jkl,userList,strings
From: https://www.cnblogs.com/lwzcode/p/17291047.html

相关文章

  • Django笔记十六之aggregate聚合操作
    本文首发于微信公众号:Hunter后端原文链接:Django笔记十六之aggregate聚合操作这一篇笔记介绍一下关于聚合的操作,aggregate。常用的聚合操作比如有平均数,总数,最大值,最小值等等用到的model如下classAuthor(models.Model):name=models.CharField(max_length=100)......
  • Failed to start bean 'documentationPluginsBootstrapper';nested exception is jav
    报错:Failedtostartbean‘documentationPluginsBootstrapper’;nestedexceptionisjava.lang.NullPointerException错误项目版本:springboot最新版本<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-sta......
  • Java进制转换
    publicstaticvoidmain(String[]args){ Scannerscan=newScanner(System.in); Stringrs="2022"; System.out.println(Integer.parseInt(rs,9)); scan.close();}上述代码实现的功能:将2022的9进制数转化为10进制......
  • 【重要】Nginx模块Lua-Nginx-Module学习笔记(三)Nginx + Lua + Redis 已安装成功(非open
    一、目标使用Redis做分布式缓存;使用luaAPI来访问redis缓存;使用nginx向客户端提供服务,ngx_lua将lua嵌入到nginx,让nginx执行lua脚本,高并发,非阻塞的处理各种请求。url请求nginx服务器,然后lua查询redis,返回json数据。二、准备工作系统环境:Ubuntu14.0(64位)Redis服务安装:ap......
  • 【精选】Nginx负载均衡学习笔记(一)实现HTTP负载均衡和TCP负载均衡(官方和OpenResty两种
    说明:很简单一个在HTTP模块中,而另外一个和HTTP是并列的Stream模块(Nginx1.9.0支持)一、两个模块的最简单配置如下1、HTTP负载均衡:http{includemime.types;default_typeapplication/octet-stream;upstreamlive_node{server127.0.......
  • 流媒体技术学习笔记之(十二)Linux(Ubuntu)环境运行EasyDarwin
     Debug问题???./easydarwin-c./easydarwin.xml&//这样的话是80端口./easydarwin-c./easydarwin.xml-d//8088端口 以上出现的问题:在调试模式下加载配置文件是可以的,但是在后台模式下配置文件是加载不了的,列如:在配置文件配置后台管理端口为8088,当时在后台模式......
  • 流媒体技术学习笔记之(十一)Windows环境运行EasyDarwin
     流媒体平台框架下载安装Github下载下载地址:https://github.com/EasyDarwin/EasyDarwin/releases解压安装选择Windows安装平台的安装包(下载解压) 把解压生成的文件夹重命名放在本地磁盘,我这里测试放在E盘: 介绍其中的来个批处理文件:start.batWindows调试运......
  • 流媒体技术学习笔记之(七)进阶教程OBS参数与清晰度流畅度的关系
     源码地址:https://github.com/Tinywan/PHP_Experience 很多主播问过OBS的参数到底什么影响画质,到底什么影响流畅度,那么本篇教程尽量用通俗的语言解释下一些重要参数到底是干什么的,自己一定要理解为主,每个主播的电脑、所在的平台、当天的网络状态(注意网络就和马路一样,每天的情......
  • 流媒体技术学习笔记之(六)FFmpeg官方文档先进音频编码(AAC)
     先进音频编码(AAC)的后继格式到MP3,和以MPEG-4部分3(ISO/IEC14496-3)被定义。它通常用于MP4容器格式; 对于音乐,通常使用.m4a扩展名。第二最常见的用途是在MKV(Matroska)文件内,因为它比MP4更好地支持嵌入式基于文本的软字幕。本指南中的示例将使用扩展MP4和M4A。FFmpeg的可支持两个AA......
  • 流媒体技术学习笔记之(四)解决问题video.js 播放m3u8格式的文件,根据官方的文档添加vide
    源码地址:https://github.com/Tinywan/PHP_Experience总结:说明:测试环境:本测试全部来自阿里云直播和OSS存储点播以及本地服务器直播和点播播放器:VideoJs直播:1、阿里云直播,需要CDN设置HTTP头2、本地直播需要设置直播访问服务器的头部信息(本地为Nginx)add_header'Access-......