Java-Stream流常用方法详解

news2024/11/15 16:02:41

概述 

Java 8引入的Stream API用于对集合(如列表、集合等)进行函数式操作(如过滤、映射、规约等)。这类流提供了一种高效且易读的方式来处理集合中的数据。 

获取Stream对象的方式有哪些个?

1 Stream接口提供的: of静态方法

public static<T> Stream<T> of(T... values) { // 传入一些T类型数据;
    return Arrays.stream(values);
}
public static<T> Stream<T> ofNullable(T t) {
    return t == null ? Stream.empty()
                     : StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
}
public static<T> Stream<T> of(T t) {
    return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
}

2 集合当中stream()方法

List/Set

default Stream<E> stream() {
    return StreamSupport.stream(spliterator(), false);
}

3 数组工具类Arrays.stream(T[] t)

public static <T> Stream<T> stream(T[] array) {
    return stream(array, 0, array.length);
}

4 基本使用

大体分为两大类方法:

  • 中间方法「返回值本身还是一个Stream对象,支持链式调用」

  • 终结方法,它不支持链式调用的.

  1. 集合的操作.通过以下方法获取Stream对象;

default Stream<E> stream() {
    return StreamSupport.stream(spliterator(), false);
}
package com.tingyi.demo04;
​
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
​
/**
 * @author 听忆
 * Stream流基本应用:
 */
public class Test01 {
    public static void main(String[] args) {
        // 搞一个集合.对集合元素进行操作;
        List<String> nameList = new ArrayList<>();
        nameList.add("张三");
        nameList.add("张三");
        nameList.add("张三");
        nameList.add("张三");
        nameList.add("张三");
        nameList.add("李四");
        nameList.add("王五");
        nameList.add("赵六");
        nameList.add("田七");
        nameList.add("孙八");
​
        // ①. 获取Stream对象;
        Stream<String> stream = nameList.stream();
        // 获取一下集合当中名称是姓张的.
        // 过滤集合元素.
        // Predicate<? super T> predicate = s -> {
        //     // 判断集合元素的逻辑写在这里.返回是一个boolean值;
        //     if(s.contains("张")){
        //         return true;
        //     }
        //     return false;
        // };
        // 应用了lambda表达式来简化操作
        // 本质: 匿名内部类对象.
        // 本质: 匿名内部类对象.  --> 真理.
        List<String> list = stream.filter(s -> s.contains("张三"))
                .collect(Collectors.toList());
        System.out.println(list);
​
    }
}
​

一个重点:

  • 当一个接口当作方法的参数的时候,实参传入的就是: 实现了这个接口的实现类的对象

  • 当一个接口当作了方法的返回值,那么返回的一定是: 实现了这个接口的实现类的对象

方法名称描述方法类型
filter针对于每个元素进行判断,符合条件的留下,不符合过滤掉了.中间方法
map把一个数据类型转换为别外一个数据类型.中间方法
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
package com.tingyi.demo04;
​
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
​
/**
 * @author 听忆
 */
public class Test02 {
    public static void main(String[] args) {
        List<String> nameList = new ArrayList<>();
        nameList.add("张三");
        nameList.add("张三");
        nameList.add("张三");
        nameList.add("张三");
        nameList.add("张三");
        nameList.add("李四");
        nameList.add("王五");
        nameList.add("赵六");
        nameList.add("田七");
        nameList.add("孙八");
​
        // 想在这个集合当中,给所有的元素都添加一个字符串,"好好学习, 天天向上!"
        // 张三-好好学习, 天天向上;
        Stream<String> stream = nameList.stream(); // Stream对象.
        List<String> newList = stream.map(s -> s + "-好好学习, 天天向上!")
                .collect(Collectors.toList());
        System.out.println(newList);
​
        // Stream特性: 一次性的对象.用完之后,不能重复使用.如果你还要用,自己搞对象;
        // Stream特性: 一次性的对象.用完之后,不能重复使用.如果你还要用,自己搞对象;
        // Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
        List<String> list1 = nameList.stream().filter(s -> s.contains("李四")).collect(Collectors.toList());
        System.out.println(list1);
​
​
         System.out.println("--------------------------------");
        // // 一步到位写法.
         List<String> list = nameList.stream()
                 .map(s -> s + "hello world!")
                 .collect(Collectors.toList());
         System.out.println(list);
​
    }
}
 

①. Stream流,只能消费一次.不能重复使用;

​ 如果重复使用则会抛出异常:

​ Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed

②. Function, t -> r, 这里使用的泛型,实际上咱们可以是同一个类型相互之间有转换;

5 将Stream还原成List/数组对象

Stream当中提供了方法:

<R, A> R collect(Collector<? super T, A, R> collector);// 参数: 实现好Collector接口的实现类的对象;
public interface Collector<T, A, R> {}

如果要自动手动实现,复杂度太高了,而且我们进行方法调用,必须得手写一个实现类。显然,这么做不太现实.jdk当中提供了工具类. Collectors

static class CollectorImpl<T, A, R> implements Collector<T, A, R> {
    private final Supplier<A> supplier;
    private final BiConsumer<A, T> accumulator;
    private final BinaryOperator<A> combiner;
    private final Function<A, R> finisher;
    private final Set<Characteristics> characteristics;
// 实现类,是在Collectors当中的一个静态内部类.
public static <T>
Collector<T, ?, List<T>> toList() {
    return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
                               (left, right) -> { left.addAll(right); return left; },
                               CH_ID);
}

上边的方法,它是定义在Collectors工具类当中的.还是一个静态的方法.方便我们直接使用类名调用.

Stream流当中,collect(Collector),表示收集方法,就是将一个stream对象转换为其它集合姿势;所以我们在使用的时候,都会借助工具类.造成别自己去写实现类.

// Supplier, 生产型接口.这里我们生产啥类型的集合,就可以将Stream转换成啥类型的集合;
public static Collector toCollection(Supplier collectionFactory) {
    return new CollectorImpl<>(collectionFactory, Collection<T>::add,
                               (r1, r2) -> { r1.addAll(r2); return r1; },
                               CH_ID);
}

将Stream流,还原一个指定的集合类型;

Supplier collectionFactory, 参数生产接口.没有入参,只有出参:

() -> { return new HashSet<>()}; –> 更改成方法引用.

// 将stream转换为字符串.
直接调用: Collectors.joining("分隔符");
Collectors.joining("分隔符", "前缀", "后缀");
​
// 示例:
String s = nameList.stream()
                .collect(Collectors.joining(",", "{", "}"));

{张三,张三,张三,张三,张三,李四,王五,赵六,田七,tom,jack,jerry,rose,齐天大圣}

6 StringJoiner

String

StringBuffer

StringBuilder

// String s1 = new String(“hello” + “world”);

StringJoiner

public StringJoiner(CharSequence delimiter, // 分隔符
                    CharSequence prefix, // 前缀
                CharSequence suffix) {} // 后缀
​
public StringJoiner(CharSequence delimiter) { // 分隔符
    this(delimiter, "", "");
}

添加串, 通过add(),可以链式调用;

Collectors, 这里边封装了大量的常用方法,该方法返回值就是实现了Collector接口的实现类的对象;

Stream对象 —> Map集合.

toMap(Function f1, Function f2)

7 分组实现

collect(Collectors.groupBy(Function f)

package com.tingyi.demo05;
​
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
​
/**
 * @author 听忆
 */
public class Test01 {
    public static void main(String[] args) {
        List<User> userList = new ArrayList<>();
        User u1 = new User(1L, "张三小", "男", "河北");
        User u2 = new User(15L, "tom", "男", "河北");
        User u3 = new User(14L, "赵小四", "女", "北京");
        User u4 = new User(13L, "马小六", "女", "北京");
        User u5 = new User(12L, "jack", "女", "上海");
        User u6 = new User(11L, "jerry", "女", "广州");
​
        userList.add(u1);
        userList.add(u2);
        userList.add(u3);
        userList.add(u4);
        userList.add(u5);
        userList.add(u6);
​
        Map<String, List<User>> listMap = userList.stream()
                .collect(Collectors.groupingBy(user -> user.getAddress()));
​
        Set<Map.Entry<String, List<User>>> entries = listMap.entrySet();
        for (Map.Entry<String, List<User>> entry : entries) {
            String key = entry.getKey();
            System.out.println(" key = " + key);
            List<User> users = entry.getValue();
            for (User user : users) {
                System.out.println(user);
            }
            System.out.println("-----------------------------------------------------------------");
        }
    }
}
​

key,填入的是分组字段的值.

value, 将符合该分组的元素都存储到了List当中;

符合条件的分为一组, 不符合条件的分为一组;

package com.tingyi.demo05;
​
import javax.naming.Name;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
​
/**
 * @author 听忆
 */
public class Test02 {
    public static void main(String[] args) {
        List<User> userList = new ArrayList<>();
        User u1 = new User(1L, "张三小", "男", "河北");
        User u2 = new User(15L, "tom", "男", "河北");
        User u3 = new User(14L, "赵小四", "女", "北京");
        User u4 = new User(13L, "马小六", "女", "北京");
        User u5 = new User(12L, "jack", "女", "上海");
        User u6 = new User(11L, "jerry", "女", "广州");
​
        userList.add(u1);
        userList.add(u2);
        userList.add(u3);
        userList.add(u4);
        userList.add(u5);
        userList.add(u6);
​
        /**
         * 将整个集合当中的分为两组.key = boolean值;
         */
        Map<Boolean, List<User>> listMap = userList.stream()
                .collect(Collectors.partitioningBy(user -> user.getSex().equals("男")));
​
        // forEach
        listMap.forEach((k, v) -> {
            System.out.println("key  = " + k);
            v.forEach(System.out::println);
            System.out.println("=====================================");
        });
    }
}
​

==总结分组实现==

前置条件都是在数据收集的时候去操作,也就是调用collect这个方法的时候,去操作分组的;

  • 分为两组, 根据条件判断,符合条件的分为一组.不符合条件的分为另外的一组;

  • 分为多组, 根据分组字段进行分组.符合字段要求的放到一个List集合.

8 聚合统计

方法如下所示:

package com.tingyi.demo06;
​
import java.util.ArrayList;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
​
/**
 * @author 听忆
 */
public class Test {
    public static void main(String[] args) {
        List<Integer> numberList = new ArrayList<>();
        numberList.add(10);
        numberList.add(20);
        numberList.add(314);
        numberList.add(8);
        numberList.add(90);
​
        // ?????? Optional , Objects
        Optional<Integer> optional = numberList.stream()
                // .collect(Collectors.maxBy((i1, i2) -> i1 - i2));
                .max((i1, i2) -> i1 - i2); // Stream流当中提供的方法,更加直观一些.推荐使用;
        Integer result = optional.get();
        System.out.println(result);
        System.out.println("--------------------------------------------------");
        IntSummaryStatistics statistics = numberList.stream()
                .collect(Collectors.summarizingInt(i -> i));
​
        System.out.println(statistics.getCount());
        System.out.println(statistics.getAverage());
        System.out.println(statistics.getMin());
        System.out.println(statistics.getSum());
        System.out.println(statistics.getMax());
    }
}
​
System.out.println("------------------------------------------------");
LongSummaryStatistics summaryStatistics = userList.stream()
    .collect(Collectors.summarizingLong(User::getId));// user -> user.getId();
​
System.out.println(summaryStatistics.getAverage());
System.out.println(summaryStatistics.getCount());
System.out.println(summaryStatistics.getMax());
System.out.println(summaryStatistics.getMin());
System.out.println(summaryStatistics.getSum());

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1868761.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Sklearn驯化-回归指标】一文搞懂机器学习中回归算法评估指标:mae、rmse等

【Sklearn驯化-回归指标】一文搞懂机器学习中回归算法评估指标&#xff1a;mae、rmse等 本次修炼方法请往下查看 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合&#xff0c;智慧小天地&#xff01; &#x1f387; 免…

Web渗透-命令执行漏洞及常见靶场探测实战

一、概述 命令执行&#xff08;RCE&#xff09;&#xff1a;应用有时需要调用一些执行系统命令的函数&#xff0c;如php中的system,exec,shell exec,passthru,popen,proc popen等&#xff0c;当用户能控制这些函数的参数时&#xff0c;就可以将恶意系统命令拼接到正常命令中&a…

Open AI不能用了,国产大模型疯狂整活

行业开启新一轮竞争。 国产大模型公司集体出手 来活了&#xff0c;国内AI大模型市场又要热闹一阵了。 近日&#xff0c;市场消息称&#xff0c;Open AI在其官方邮件表示&#xff0c;**从7月9日开始&#xff0c;将采取额外措施阻止来自非支持国家和地区的API&#xff08;应用程…

SyntaxError: Unexpected token ‘<‘ (at chunk-vendors.fb93d34e.js:1:1)打包后页面白屏vue

本地运行一切正常&#xff0c;打包到线上&#xff0c;页面一篇空白。我确定输入路径正确。。。 控制台报错&#xff0c;我就开始百度&#xff0c;有的说清空缓存就行了&#xff0c;但我清空了还是这样。。。 然后我就去排查原因。看到页面请求js&#xff0c;但是请求的好像有点…

气膜体育馆对高度的要求—轻空间

在现代体育场馆的建设中&#xff0c;气膜体育馆以其独特的优势&#xff0c;逐渐成为人们关注的焦点。不同于传统的钢筋混凝土结构&#xff0c;气膜体育馆以其轻盈、灵活、环保的特点&#xff0c;为人们带来了全新的体育体验。在设计与建设气膜体育馆时&#xff0c;高度是一个关…

AI数据分析007:根据Excel表格数据绘制柱形图

文章目录 一、介绍二、输入内容三、输出内容一、介绍 将Excel文件中2013年至2019年间线上图书的销售额,以条形图的形式呈现,每个条形的高度代表相应年份的销售额,同时在每个条形上方标注具体的销售额数值 二、输入内容 在deepseek中输入提示词: 你是一个Python编程专家,…

线性代数|机器学习-P16矩阵A的导数

文章目录 1. 概述2. 求 d A − 1 ( t ) d t \frac{\mathrm{d}A^{-1}(t)}{\mathrm{d}t} dtdA−1(t)​3. 求 d λ ( t ) d t \frac{\mathrm{d}\lambda(t)}{\mathrm{d}t} dtdλ(t)​3.1 A 和 A T A^T AT有相同的特征值3.2 特征向量单位化3.3 求 λ ( t ) \lambda(t) λ(t) 4. 交替…

手持小风扇哪个牌子比较好?五大手持小风扇品牌推荐

随着夏季的到来&#xff0c;气温日益升高。除了空调&#xff0c;各式各样的小风扇成为当下年轻人的热门宠儿。但是市面上的种类比较多&#xff0c;很多人都不知道该怎么选择&#xff0c;因为我也是买过很多产品了&#xff0c;收获了一些经验&#xff0c;接下来就把我觉得比较好…

大模型们拿着锤子找钉钉

今年的大模型赛道&#xff0c;看不见硝烟&#xff0c;却是一个白热化的战场。 这背后是对更大场景、更大规模用户入口和先发优势的争夺。在AGI尚未到来的当下&#xff0c;行业有一个共识&#xff1a;真实场景中的大规模应用&#xff0c;是大模型价值验证和通往AGI的必由之路。…

WPS-Word文档表格分页

一、问题描述 这种情况不好描述 就是像这种表格内容&#xff0c;但是会有离奇的分页的情况。这种情况以前的错误解决办法就是不断地调整表格的内容以及间隔显得很乱&#xff0c;于是今天去查了解决办法&#xff0c;现在学会了记录一下避免以后忘记了。 二、解决办法 首先记…

一键系统重装教程:电脑重装系统,5个方法轻松恢复电脑

在日常使用电脑的过程中&#xff0c;难免会遇到系统故障、运行缓慢或者病毒感染等问题&#xff0c;重装系统成为解决这些问题的有效途径。然而&#xff0c;对于许多小伙伴来说&#xff0c;电脑重装系统似乎是一项复杂且耗时的任务。其实&#xff0c;只要掌握了正确的方法&#…

什么是港股通?港股通碎股如何进行交易佣金最低万0.8?

港股通是一种投资渠道&#xff0c;它允许符合条件的内地投资者通过内地的证券账户&#xff0c;间接地买卖在香港联合交易所上市的股票。这一机制是沪港通和深港通计划的一部分&#xff0c;旨在促进内地与香港资本市场的互联互通。 ### 港股通的特点包括&#xff1a; - 交易范…

AI大模型会有意识的出千吗?

1. 引言 1.1 研究背景&#xff0c;AI系统中的规范游戏问题 在人工智能(AI)系统的发展过程中&#xff0c;规范游戏(specification gaming)一直是一个令研究者们头疼的问题。规范游戏指的是AI系统学习到一些意想不到的行为&#xff0c;这些行为虽然能够获得高奖励&#xff0c;但…

上班族真的有必要买智能猫砂盆吗?解放双手刻不容缓!

养猫家庭真是出不了一点远门&#xff0c;但凡外出的时间久了&#xff0c;家里的猫屎就堆积成山&#xff0c;不及时铲掉的话&#xff0c;回来一进门就能在猫砂盆中挖出满满当当的“宝藏”&#xff0c;仔细一闻还能闻到空气中散发的阵阵“清香”。忍无可忍的我最后借助科技的力量…

浅谈逻辑控制器之随机控制器

浅谈逻辑控制器之随机控制器 随机控制器(Random Controller)是众多逻辑控制器中的一种&#xff0c;它为测试脚本引入了随机性&#xff0c;提高了模拟真实用户行为的灵活性。 随机控制器的功能 随机控制器的作用在于从其直接子元素&#xff08;通常是采样器&#xff09;中随机…

“ONLYOFFICE 8.1版本评测:功能更强大,用户体验更佳”

最新版本的在线编辑器已经发布 ONLYOFFICE在线编辑器的最新版本8.1已经发布&#xff0c;整个套件带来了30多个新功能和432个bug修复。这个强大的文档编辑器支持处理文本文档、电子表格、演示文稿、可填写的表单和PDF&#xff0c;并允许多人在线协作&#xff0c;同时支持AI集成…

火山引擎ByteHouse:新一代云数仓必不可少的五大核心能力

从数据库领域的发展历程来看&#xff0c;分析型数据库已有 40 多年的发展历史&#xff0c;与数据库基本同时代。从OLTP 和 OLAP 的分支来看&#xff0c;分析型数据库支持了海量数据规模下的聚合性分析。尤其是随着移动互联网甚至 AI 等领域的发展&#xff0c;用户画像行为分析的…

C#校园在线投票系统-计算机毕业设计源码10577

摘 要 随着互联网大趋势的到来&#xff0c;社会的方方面面&#xff0c;各行各业都在考虑利用互联网作为媒介将自己的信息更及时有效地推广出去&#xff0c;而其中最好的方式就是建立网络管理系统&#xff0c;并对其进行信息管理。由于现在网络的发达&#xff0c;校园投票通过网…

AI产品经理如何快速接手一个新产品?

我们到一家新的公司&#xff0c;往往都有现成的产品需要你熟悉&#xff0c;这个对你来说就是一个新产品。 又或者说&#xff0c;公司要搭建一个新的项目&#xff0c;让你负责&#xff0c;需要你从0开始去接手&#xff0c;最终去上线&#xff0c;去推广&#xff0c;去盈利&…

项目实训-vue(八)

项目实训-vue&#xff08;八&#xff09; 文章目录 项目实训-vue&#xff08;八&#xff09;1.概述2.医院动态图像轮播3.页面背景板4.总结 1.概述 除了系统首页的轮播图展示之外&#xff0c;还需要在医院的首页展示医院动态部分的信息&#xff0c;展示医院动态是为了确保患者、…