首页 > 编程语言 >Java Stream流以及常用方法详解

Java Stream流以及常用方法详解

时间:2024-11-22 18:15:38浏览次数:3  
标签:Java Stream stream System 详解 println 操作 out

目录

一、Stream流是什么?

二、stream的操作


一、Stream流是什么?

Stream流是Java 8中的一个新特性,它提供了一种处理集合和数组的方式。Stream流可以让我们以一种更加简洁、高效、可读性更强的方式来处理数据。,这个版本新增的Stream,配合同版本出现的 Lambda ,给我们操作集合(Collection)提供了极大的便利。Stream流可以用于过滤、映射、排序、聚合等操作,它可以让我们避免使用循环和条件语句来处理数据,从而让代码更加简洁易懂。

那么什么是Stream

Stream将要处理的元素集合看作一种流,在流的过程中,借助Stream API对流中的元素进行操作,比如:筛选、排序、聚合等。是一种基于支持一次性处理数据的数据源的元素序列,流只能使用一次。

关于对Stream流的理解,你可以把他当成工厂中的流水线,每个stream流的操作过程遵循着创建 -->操作 -->获取结果的过程,就像流水线上的节点一样组成一个个链条。除此之外你还可以把他理解成sql的视图,集合就相当于数据表中的数据,获取stream流的过程就是确定数据表的属性和元数据的过程,元数据的每一个元素就是表中的数据,对stream流进行操作的过程就是通过sql对这些数据进行查找、过滤、组合、计算、操作、分组等过程,获取结果就是sql执行完毕之后获取的结果视图一样,深入理解stream流可以让我们使用更加简洁的代码获取自己想要的数据。

流的设计初衷是为了支持函数式编程,它的目的是将数据处理和数据存储分离开来,使得数据处理更加灵活和高效。因此,流的元素只是在流中传递的临时数据,它们并不是永久存储在内存中的数据。当流的元素被消费后,它们就会被释放,不能再次使用.

如果需要对同一个数据集进行多次不同的操作,可以使用流的中间操作方法来构建多个流管道,每个流管道都可以对流进行不同的操作,并返回一个新的流。这样就可以对同一个数据集进行多次操作,而不需要重新获取数据集。

所以说Stream可以由数组或集合创建,对流的操作分为两种:

  1. 中间操作,每次返回一个新的流,可以有多个。
  2. 终端操作,每个流只能进行一次终端操作,终端操作结束后流无法再次使用。终端操作会产生一个新的集合或值。

另外,Stream有几个特性:

  1. stream不存储数据,而是按照特定的规则对数据进行计算,一般会输出结果。
  2. stream不会改变数据源,通常情况下会产生一个新的集合或一个值。
  3. stream具有延迟执行特性,只有调用终端操作时,中间操作才会执行。也就是说只有等到用户真正需要结果的时候才会执行

二、stream的操作

2.1、stream流创建

获取stream流的方式有许多种,最常用的有以下几种:

  1. Collection接口的stream()或parallelStream()方法;
ArrayList<String> list=new ArrayList();
Collections.addAll(list,"a,b,c,d");
//ArrayList是Collection的实现类所以可以使用Collection的stream方法
list.stream().forEach(s -> System.out.println(s)); //Stream流方法获取数据
//map
HashMap<String,Integer> map=new HashMap<>();
map.put("aaa",111);
map.put("bbb",222);
map.put("ccc",333);
map.put("ddd",444);

//获取Stream流
map.keySet().stream().forEach(s -> System.out.println(s));
//第二种方式
map.entrySet().stream().forEach(stringIntegerEntry -> System.out.println(stringIntegerEntry));

streamparallelStream的简单区分: stream是顺序流,由主线程按顺序对流执行操作,而parallelStream是并行流,内部以多线程并行执行的方式对流进行操作,但前提是流中的数据处理没有顺序要求。例如筛选集合中的奇数,两者的处理不同之处:

  1. Arrays工具类的stream()方法:Arrays.stream(arr);
//数组
int [] arr ={1,2,3,4,5};
String [] stringArr={"哈哈","哈哈哈","哈哈哈"};

//获取stream流
Arrays.stream(arr).forEach(s-> System.out.println(s));
Arrays.stream(stringArr).forEach(s -> System.out.println(s));
  1. 静态的Stream.of()、Stream.empty()方法;
//零散数据stream流
Stream.of(1,2,3,4).forEach(s-> System.out.println(s));

Stream.of("6","7","8","9").forEach(s-> System.out.println(s));

注:

有关of方法的使用还有List.of()、Set.of()、Map.of()的方式创建各种集合,其表示的含义都是不可变集合,表示不允许修改集合内任何内容。

Stream.of(arr)中还可以传递数组但必须是引用类型的,而不是基本类型的,比如数组类中的stringArr,如果传递的是arr基本类型数组,那么会打印一个对象地址,不符合我们想要的效果.

2.2、stream的使用

Stream流接口中定义了许多对于集合的操作方法,总的来说可以分为两大类:中间操作和终端操作:

  1. 中间操作:会返回一个流,通过这种方式可以将多个中间操作连接起来,形成一个调用链,从而转换为另外 一个流。除非调用链后存在一个终端操作,否则中间操作对流不会进行任何结果处理。
  2. 终端操作:会返回一个具体的结果,如boolean、list、integer等。

2.2.1、中间操作-filter(筛选)

筛选,是按照一定的规则校验流中的元素,将符合条件的元素提取到新的流中的操作。

ArrayList<String> list=new ArrayList();
Collections.addAll(list,"张三丰","张二封","乔峰","傅红雪","张三丰","乔峰");
//filter 过滤/筛选
list.stream().filter(s -> s.startsWith("张")).forEach(s -> System.out.println(s));

//运行结果
张三丰
张二封
ArrayList<Integer> arrayList=new ArrayList<>();
Collections.addAll(arrayList,1,2,3,4,6,7,8);
arrayList.stream().filter(x-> x>6).forEach(x-> System.out.println(x)); //筛选出大于6的

//运行结果
7
8
2.2.2、中间操作-limit

获取前几个元素,不是索引,就是单纯个数。

 //limit 获取前几个元素 与索引无关  就是单纯前几个
arrayList.stream().limit(3).forEach(s-> System.out.print(s));
//运行结果
123
2.2.3、中间操作-skip

跳过前几个元素

//skip  跳过前几个元素
arrayList.stream().skip(3).forEach(s-> System.out.print(s));
//运行结果
4678
2.2.4、中间操作-distinct

元素去重,依赖于hashcode和equals方法(底层利用hashSet()方法去重)

//distinct 去重 依赖hashcode和equals方法
list.stream().distinct().forEach(s -> System.out.println(s));
//运行结果
张三丰
张二封
乔峰
傅红雪
2.2.5、中间操作-concat

合并两个流:Stream.concat(stream1,stream2)

//concat 合并两个流
Stream.concat(list.stream(),arrayList.stream()).forEach(s -> System.out.println(s));
//运行结果
张三丰
张二封
乔峰
傅红雪
张三丰
乔峰
1
2
3
4
6
7
8
2.2.6、中间操作-map

转换流中数据类型,返回一个新的流

//map  转换流中的数据结构
arrayList.stream().map(s->String.valueOf(s)).forEach(s -> System.out.println(s));
//运行结果
数组中整数全部转换为了string类型

2.2.7、终端操作-foreach

遍历方法,终端操作表示调用该方法后不能再使用该流。

   list.stream().distinct().forEach(s -> System.out.println(s));
2.2.7、终端操作-count

统计计数

//终端方法 foreach  count()
long count = list.stream().count();
System.out.println(count);
//运行结果
6
2.2.8、终端操作-toArray()

收集流中的数据,放到数组中。

String[] strings = list.stream().toArray(value -> new String[value]);
System.out.println(Arrays.toString(strings));

//运行结果
[张三丰, 张二封, 乔峰, 傅红雪, 张三丰, 乔峰]
2.2.9、终端操作-collect()

collect,收集,可以说是内容最繁多、功能最丰富的部分了。从字面上去理解,就是把一个流收集起来,最终可以是收集成一个值也可以收集成一个新的集合。

collect主要依赖java.util.stream.Collectors类内置的静态方法。

归集(toList/toSet/toMap)

因为流不存储数据,那么在流中的数据完成处理后,需要将流中的数据重新归集到新的集合里。toList、toSet和toMap比较常用,另外还有toCollection、toConcurrentMap等复杂一些的用法。

//  toList 将流中的数据转换为一个新的集合
List<String> newList = list.stream()
                            .filter(s -> s.startsWith("张"))
                            .collect(Collectors.toList());
//运行结果
[张三丰, 张二封, 张三丰]
//toSet集合
Set<String> newSet = list.stream()
                                .filter(s -> s.startsWith("张"))
                                .collect(Collectors.toSet());
System.out.println("newSet = " + newSet);
//运行结果
newSet = [张三丰, 张二封]
     Map<String, String> collect = list.stream()
                .distinct()
                .filter(s -> s.startsWith("傅"))
                .collect(Collectors.toMap(k -> k.split("红")[0], v -> v.split("红")[1]));
        System.out.println(collect);

统计(count/averaging)

Collectors提供了一系列用于数据统计的静态方法:

  • 计数:count
  • 平均值:averagingInt、averagingLong、averagingDouble
  • 最值:maxBy、minBy
  • 求和:summingInt、summingLong、summingDouble
  • 统计以上所有:summarizingInt、summarizingLong、summarizingDouble

public class StreamTest {
	public static void main(String[] args) {
		List<Person> personList = new ArrayList<Person>();
		personList.add(new Person("Tom", 8900, 23, "male", "New York"));
		personList.add(new Person("Jack", 7000, 25, "male", "Washington"));
		personList.add(new Person("Lily", 7800, 21, "female", "Washington"));

		// 求总数
		Long count = personList.stream().collect(Collectors.counting());
		// 求平均工资
		Double average = personList.stream().collect(Collectors.averagingDouble(Person::getSalary));
		// 求最高工资
		Optional<Integer> max = personList.stream().map(Person::getSalary).collect(Collectors.maxBy(Integer::compare));
		// 求工资之和
		Integer sum = personList.stream().collect(Collectors.summingInt(Person::getSalary));
		// 一次性统计所有信息
		DoubleSummaryStatistics collect = personList.stream().collect(Collectors.summarizingDouble(Person::getSalary));

		System.out.println("员工总数:" + count);
		System.out.println("员工平均工资:" + average);
		System.out.println("员工工资总和:" + sum);
		System.out.println("员工工资所有统计:" + collect);
	}
}

运行结果:
员工总数:3
员工平均工资:7900.0
员工工资总和:23700
员工工资所有统计:DoubleSummaryStatistics{count=3, sum=23700.000000,min=7000.000000, average=7900.000000, max=8900.000000}

总结:

image.png

标签:Java,Stream,stream,System,详解,println,操作,out
From: https://blog.csdn.net/Tomkruse11/article/details/143918733

相关文章

  • Java根据前端返回的字段名进行查询数据的方法
    在Java后端开发中,根据前端返回的字段名动态查询数据库是一种常见的需求。这种需求通常通过使用反射和动态SQL来实现。下面是一个完整的代码示例,它展示了如何根据前端返回的字段名动态查询数据库中的数据。一、根据前端返回的字段名动态查询数据库中的数据示例1.准备工作(1)数据库......
  • SAP S/4HANA Cloud模块功能详解:开启企业数字化转型新篇章
    在数字化转型浪潮的推动下,企业纷纷寻求高效、灵活且可扩展的解决方案,以应对日益复杂的市场环境。SAPS/4HANACloud作为SAP公司推出的云端ERP(企业资源规划)解决方案,凭借其强大的功能和云技术的结合,成为了众多企业数字化转型的首选。本文将深入探讨SAPS/4HANACloud的几大核心模块......
  • 数字孪生如何赋能智慧工厂?核心作用详解
    近年来,随着智能制造的发展,数字孪生技术逐渐成为智慧工厂的核心技术之一。它通过将物理世界的生产设备、流程和环境实时映射到虚拟空间,实现了物理与数字的无缝连接。这种融合不仅提升了工厂运营效率,还为企业实现更高层次的智能化转型奠定了基础。那么,数字孪生在智慧工厂中究竟能够......
  • JAVA-PTA题目集2总结
    ​前言    经过这几次JAVA练习题的训练,我对JAVA编程语言有了更深入的理解,同时在程序开发设计环节也有了很大的进步,吸收了上次编程练习的教训后,我在本阶段的编程练习中也有针对性的进行了改进。    本次的JAVA练习内容丰富,包括各种数据结构的应用,如哈希表,列表......
  • Java中的公平锁和非公平锁
    公平锁和非公平锁是多线程编程中对锁获取策略的两种不同实现,主要区别在于锁对等待线程的调度方式。公平锁公平锁(FairLock)遵循先来先服务的原则,线程按照请求锁的顺序依次获取锁。特点排队机制:线程请求锁时,如果锁被占用,会进入一个等待队列。当锁被释放时,队列中等待......
  • 【揭秘】JVM类加载器子系统:Java程序员的隐藏武器,你掌握了吗?
    Java虚拟机(JVM)的类加载器子系统是Java平台的核心组件之一,它负责在运行时动态地加载Java类。类加载器子系统通过将类的字节码转换为JVM可以执行的格式,使得Java程序能够实现高度的灵活性和可扩展性。下面将详细解释JVM类加载器子系统的工作原理、结构以及代码示例。打开免费领取......
  • 揭秘JVM性能优化:深入理解运行时数据区,让你的Java应用飞起来!
    Java虚拟机(JVM)的运行时数据区是程序执行期间管理和存储各种信息的关键部分。理解这些区域有助于深入掌握JVM的工作原理和性能优化。以下是对JVM运行时数据区的详细解析:打开免费领取面试资料https://fhos.urlint.cn/cHVLFV一、程序计数器(ProgramCounterRegister)定义:程序计......
  • GET、POST、PUT 的区别与使用场景详解
    大家好,我是小黄。在现代Web开发中,GET、POST和PUT是常用的HTTP请求方法,每种方法都对应不同的用途。理解它们的作用和使用场景,不仅能让接口设计更加清晰,还能提升系统的可维护性。本文将以简洁易懂的方式带你了解这些HTTP方法。1.什么是HTTP方法?HTTP方法是客户端与服务......
  • 基于java和微信小程序实现投票评选系统项目【项目源码+论文说明】计算机毕业设计
    基于java和微信小程序实现投票评选系统演示【内附项目源码+LW说明】摘要越来越多信息化融入到我们生活当中的同时,也在改变着我们的生活和学习方式,当然,变化最明显的除了我们普通民众之外,要数高校学生的生活方式以及校园信息化的变革。智慧是改变生活和生产的一种来源,那么智......
  • Java基础知识(八)
    文章目录异常Exception和Error有什么区别?CheckedException和UncheckedException有什么区别?Throwable类常用方法有哪些?try-catch-finally如何使用?finally中的代码一定会执行吗?如何使用`try-with-resources`代替`try-catch-finally`?异常使用有哪些需要注意的......