首页 > 编程语言 >java流之Stream

java流之Stream

时间:2025-01-22 15:45:56浏览次数:1  
标签:java Stream stream 流之 filter operator 操作 method Classify

java流之Stream

流:在现实中有移动,传播,延绵不绝, 其有难寻其源,难觅其踪,变约莫测等特点。

stream:是jdk8中新增的api成员,是对容器对象功能的增强,借助于同样是新出现的Lambda表达式,提供了方便、简洁、高效、链式等方式处理集合容器,以获取自己需要的结果。

java中的流stream与现实中的流同中有异,异中有同。相同之处是stream也是有移动,传播,延绵不绝(链式调用处理,一个函数处理完成后传递到下一个函数处理,直至自己需要的结果)。不同处stream有清晰确认的源头(集合),及清楚的知道了自己需要的结果。

stream流从业务逻辑说起、

数据的来源也许是广泛、复杂、无序的。而我们需要用到的数据往往不是直接取用,而是通过有条件的筛选、排序、计算、转化等操作后才获取到所需的数据。

假设有一个数字集合,我们需要获取大于5的值,且需要按大小来排序。如下集合。

List<Integer> numbers = Arrays.asList(1,4,3,2,6,5,8,11,9,15,10,12,7);

在没有stream流之前。使用jdk7的处理方式。

	List<Integer> numbersGt5 = new ArrayList<Integer>(); //创建一个接收对象集合
	for(Integer i : numbers) {  //用Iterator更好,iterator只能单向的移动操作,不能做增,删等操作)。
		if(i > 5) numbersGt5.add(i); //遍历对象,获取大于5的对象加入接收集合
	}
	Collections.sort(numbersGt5); //委托给Collections做排序操作。

jdk8引入Stream流之后的处理方式。

List<Integer> numbersGt5 = numbers.stream().filter(item -> item > 5).sorted().collect(Collectors.toList());

两种处理方式。从感观上讲,使用stream流处理数据,简洁明了,要比以前的处理方式少了很多代码。链式一个方法一个法衔接调用,根据方法名称和方法的注释也能很容易猜测调用的操作流程。最后返回处理后的集合。

其实处理数据的流程一般都是大同小异,stream流的特点是封装了很多实现的具体的实现细节,让你更好的专注了业务编写。Stream相当于一个管道,每调用一个方法就相当于有一个阀门做各种操作的处理过滤转换,最终返回需要的结果。还有一点,Stream流可以方便并行地处理业务数据,在大数据量的情况下带来了性能的提升,而只需要很方便的把numbers.stream() 替换为 numbers.parallelStream()即可,就可享受多核并行带来的快乐!

Stream的特点
  1. 流水式:很多方法返回的也是一个流(如fiter\map\storted返回的也是一个stream流),返回流可方便的将处理链式衔接起来,构成一个流水式的处理方式,方便做优化处理。
  2. 数据的内部迭代:调用的很多处理方法如filter\map\storted都会经历过一系列的内部的循环对比提供,但是他的内部数据的循环外部是无感知的。
  3. 一个流,内部只可迭代一次,迭代完之后流即关闭,即流只可消费一次。如下示例。
		List<Integer> numbers = new ArrayList<> (Arrays.asList(1,4,3,2,6,5,8,11,9,15,10,12,7)); //创建集合
		Stream<Integer> stream =  numbers.stream();  //获取流
		
//		stream.forEach(i -> System.out.println(i)); //第一次迭代了正常
//		stream.forEach(i -> System.out.println(i)); //每二次迭代  报异常stream has already been operated upon or closed
		
		stream.filter(item -> true);//(请先注释掉上面的循环forEach)过滤器亦然,内部也使用了迭代,也只可处理一次。
		stream.filter(i -> i > 25);//每二次处理,报异常stream has already been operated upon or closed
Stream的操作分类

stream流的操作可将其分为两类

  1. filter、map、limit、sorted等方法操作后返回stream流对象。可以继续链式调用形成一条流水行执行。称为中间操作。
  2. collect等方法操作后,关闭流,执行可变还原操作。称为终端操作。

中间操作

中间操作给我们带来了两个特性。

  1. 延后触发。当我们执行终端操作时才会执行中间操作。
  2. 循环合并。多个需要循环操作的动作合并了为一个循环,更加的高效了。

我们从下面的代码来体验一下中间操作给我们带来的体验感

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Person {
	
	private final int age;
	private final String name;
	private final Classify type;

	public Person(int age, String name, Classify type) {
		super();
		this.age = age;
		this.name = name;
		this.type = type;
	}
	
	public int getAge() {
		return age;
	}

	public String getName() {
		return name;
	}
	
	public Classify getType() {
		return type;
	}
	
	public enum Classify{
		MAN,WOMAN;
	}
	
	@Override
	public String toString() {
		return "Person [age=" + age + ", name=" + name + ", type=" + type + "]";
	}

	public static void main(String[] args) {
		List<Person> persons = Arrays.asList(new Person(10,"小明",Classify.MAN),new Person(32,"李丽",Classify.WOMAN),new Person(35,"张三",Classify.MAN),
				new Person(18,"李雪",Classify.WOMAN),new Person(40,"杨华",Classify.WOMAN),new Person(21,"刘光",Classify.MAN),
				new Person(60,"张菲",Classify.MAN),new Person(72,"刘老师",Classify.WOMAN),new Person(90,"王大力",Classify.MAN));
		persons
		.stream()
		.filter(item ->{   // 过滤,获取男人且已成年的人员信息
			System.out.println("operator filter method!"); //添加打印,确认是否有执行该操作
			return item.getType() == Classify.MAN && item.getAge() > 18;
		})
		.map(item -> {
			System.out.println("operator map method!");//添加打印,确认是否有执行该操作
			 return item.getName();
	     })  //获取名称
		//.limit(1) //只取1个
		//.collect(Collectors.toSet()) //终端操作,将流变为Set集合,并关闭流。
		;
	}

}

将我们的目光移动到man函数中,在这个代码中,我们执行2个小操作。

1、给 .collect(Collectors.toSet()) 添加注释//【//.collect(Collectors.toSet())】,运行该程序代码。从执行情况来看控制台,无任何的信息打印。说明了调用的filter\map等方法没有执行。

2、将//.collect(Collectors.toSet()) 的注释放开【.collect(Collectors.toSet())】,运行该程序代码,可能看到如下打印信息

operator filter method!
operator filter method!
operator filter method!
operator map method!
operator filter method!
operator filter method!
operator filter method!
operator map method!
operator filter method!
operator map method!
operator filter method!
operator filter method!
operator map method!

执行操作1,说明注释//.collect(Collectors.toSet()),没有执行调用的打印信息,表明了如果没有执行终端操作是不会触发中间操作。

执行操作2,放开.collect(Collectors.toSet())终端操作。打印了信息,与上面操作1相互印证了,中间操作具有延迟执行功能。

从打印的信息中看打印的顺序是不规范的。filter方法与map方法的参数交互替代互换打印,表明了只要前一个参数结果满足条件马上传递给参数传递给下一个继续处理,而不是一个中间操作执行完再执行下一个中间操作,是得到一个正确的结果马上传递给下一个中间操作处理,即本来需要多个循环才能完成的功能,合并到了一个循环。

执行操作3,放开.limit(1)的注释。再次查看打印信息如下。

operator filter method!
operator filter method!
operator filter method!
operator map method!

从打印信息上看,只打印了四次。从persions集合中看,第三个数据,则好满足了filter过滤条件性别男,大于18岁。把筛选出的第三个数据马上传递到下个中间操作map获取到名称,再马上传递到limit 操作,判断上已经满足了只取一个数据的条件。马上停止了循环。减少了不必要的操作,节省了效率,也再次映证了循环合并猜想,也引出了另一个功能短路。短路,满足了所有的条件之后马上退出循环。不再消费CPU。流的计算也是按需计算的。

终端操作

中间操作返回的都是stream对象。终端操作是从流水线中获取生成的结果。理论上所有返回不是stream对象的操作都是终端操作。比如foreach/count/collect方法都是终端操作。他是流水线最终的结果。

标签:java,Stream,stream,流之,filter,operator,操作,method,Classify
From: https://www.cnblogs.com/crowing-bird/p/18686193

相关文章

  • Stream流操作
    Stream流操作一、过滤估计很多人学习stream流大部分是从filter方法开始,该方法筛选出满足条件的数据组成一个新的流。我们从示例中感觉一下该方法的作用。 List<Integer>numbers=Arrays.asList(1,4,2,5,3,7,120,60,54,88,88,90,11); List<Integer>list=numbers......
  • CentOS Stream 9部署MariaDB
    安装MariaDB软件包(替代mysql)sudodnfinstallmariadb-server 3、安装MariaDB服务sudosystemctlenable--nowmariadb 4、检查MariaDB服务状态sudosystemctlstatusmariadb 5、配置MariaDB安全性sudomysql_secure_installation 按照提示设置MariaDB的root密......
  • Javase--基础语法上
    Javase--基础语法注释packageMistiest.com.cnblogs.comment;/***这里介绍注释的基本语法,这个是文本注释,一般写在方法的最前面*/publicclasscomment{publicstaticvoidmain(String[]args){//这是单行注释/*这是多行注释......
  • JavaScript 自定义获取当前日期和时间的函数
    JavaScript自定义获取当前日期和时间的函数 /***获取当前的日期和时间*格式为yyyy-MM-ddHH:mm:ss.SSS*/functiongetNowDateTime(){varnow=newDate,year=now.getFullYear(),month=now.getMonth()+1......
  • Java请求接口并终止线程
    在Java开发中,处理多线程操作是常见需求。有时我们需要在请求某个接口后,根据接口返回结果或其他条件,终止某个线程的执行。本文将详细介绍如何在Java中请求接口并终止特定线程的方法。一、请求接口1.1使用 HttpURLConnectionJava提供了多种方式进行HTTP请求,这里介绍使用 HttpU......
  • 基于Java Web的健身房管理系统
    一、系统架构与技术选型系统架构:该系统通常采用三层架构,即表现层、业务逻辑层和数据访问层。这种架构使得系统结构清晰,易于维护和扩展。技术选型:前端:前端界面一般使用HTML、CSS和JavaScript等技术进行开发,以实现用户友好的交互界面。后端:后端则借助JavaServlets、JSP或......
  • 基于Java的共享汽车管理系统
    一、系统背景与意义随着城市化进程的加速和环保意识的提升,共享汽车作为一种新型的出行方式,正逐渐改变着人们的出行习惯。它不仅有效缓解了城市交通拥堵问题,还促进了资源的合理利用与节能减排。然而,随着共享汽车市场的不断扩大,其管理问题也日益凸显,如车辆调度、用户管理、费......
  • 基于Java的零食销售系统
    一、系统背景与意义随着电子商务的快速发展和消费者对零食需求的多样化、个性化提升,构建一个基于Java的零食销售系统显得尤为重要。该系统能够打破传统零售模式的地理和时间限制,满足消费者随时随地购买零食的需求,同时也为商家提供了更广阔的市场和更多的潜在客户。二、系......
  • 「2024 博客之星」自研Java框架 Sunrays-Framework 使用教程
    文章目录0.序言我的成长历程遇到挫折,陷入低谷重拾信心,迎接未来开源与分享我为何如此看重这次评选最后的心声1.概述1.主要功能2.相关链接2.系统要求构建工具框架和语言数据库与缓存消息队列与对象存储3.快速入门0.配置Maven中央仓库1.打开settings.xml2.不要配置阿里云......
  • 2024年CSDN博客年度总结 Java | 成神之路
    目录 博客创作之旅的前期沉淀年度创作成果​编辑博客创作历程创作风格与技巧创作收获与成长未来规划结束语 博客创作之旅的前期沉淀我于2020年入驻CSDN,初涉技术领域时,作为Java编程的小白,并未即刻投身创作。彼时,我将大量精力投入到知识汲取中。学习期间,我对笔......