流处理详解

news2024/11/17 1:53:38

  

【今日】

目录

一   Stream接口简介 

  Optional类

Collectors类

 二   数据过滤

1.  filter()方法

 2.distinct()方法

3.limit()方法 

 4.skip()方法

 三   数据映射

 四   数据查找

1. allMatch()方法

 2. anyMatch()方法

3. noneMatch()方法

  4. findFirst()方法

 五   数据收集

1.数据统计

 2.数据分组


 

流处理有点类似数据库的SQL语句,可以执行非常复杂的过滤、映射、查找和收集功能,并且代码量很少。唯一的缺点是代码可读性不高,如果开发者基础不好,可能会看不懂流API所表达的含义。

我们再这里先创建一个公共类----Employee 员工类,方便后续的流处理。

员工的集合数据

姓名(name)年龄(age)薪资(salary)性别(sex)部门(dept)
老张409000运营部
小刘245000开发部
大刚327500销售部
翠花285500销售部
小马213000开发部
老王356000人事部
小王213000人事部
import java.util.ArrayList;
import java.util.List;

public class Employee {//员工类
	private String name;                //姓名
	private int age;                    //年龄
	private double salary;              //薪资
	private String sex;                 //性别
	private String dept;                //部门
	
	public Employee(String name, int age, double salary, String sex, String dept) {//构造方法
		this.name = name;
		this.age = age;
		this.salary = salary;
		this.sex = sex;
		this.dept = dept;
	}

	public String toString() {//重写toString()方法,输出员工信息
		return "姓名:" + name + ", 年龄:" + age + ", 薪资:" + salary + ", 性别:" + sex + ", 部门:" + dept;
	}
	//以下是获得员工相关信息的方法
	public String GetName() {//获得名字的方法
		return name;
	}
	
	public int GetAge() {//获得年龄的方法
		return age;
	}
	public double GetSalary() {//获得薪资的方法
		return salary ;
	}
	public String GetSex() {//获得性别的方法
		return sex;
	}
	public String Getdept() {//获得部门的方法
		return dept;
	}
	static List<Employee>GetEmpList(){
		List<Employee> list = new ArrayList<>();
		list.add(new Employee("老张",40,9000,"男","运营部"));
		list.add(new Employee("小刘",24,5000,"女","开发部"));
		list.add(new Employee("大刚",32,7500,"男","销售部"));
		list.add(new Employee("翠花",28,5500,"女","销售部"));
		list.add(new Employee("小马",21,3000,"男","开发部"));
		list.add(new Employee("老王",35,6000,"女","人事部"));
		list.add(new Employee("小王",21,3000,"女","人事部"));
		return list;	
	}
}

一   Stream接口简介 

流处理的接口都定义在java.uil.stream包下。BaseStream接口是最基础的接口,但最常用的是BaseStream接口的一个子接口——Stream接口,基本上绝大多数的流处理都是在Stream接口上实现的。所忆, Stream接口是泛型接口,所以流中操作的元素可以是任何类的对象。

 Stream接口的常用

中间操作和终端操作。中间操作类型的方法会生成一个新的流对象,被操作的流对象仍然可以执行其他操作;终端操作会消费流,操作结束之后,被操作的流对象就不能再次执行其他操作了。这是两者的最大区别。 

 collection接口新增两个可以获取流对象的方法。第一个方法最常用,可以获取集合的顺序流,方下:

Stream<E> stream();

第二个方法可以获取集合的并行流,方法如下:

Stream<E> parallelstream();

因为所有集合类都是Collection接口的子类,如ArrayList类、HashSet类等,所以这些类都可以进行流处理。例如:

List<Integer> list = new ArrayList<Integer>(); //创建集合
Stream<Integer> s = list.stream(); //获取集合流对象

  Optional类

Optional类像是一个容器,可以保存任何对象,并且针对 NullPointerException空指针异常做了化,保证Optional类保存的值不会是null。因此,Optional类是针对“对象可能是null也可能不是mlr的场景为开发者提供了优质的解决方案,减少了烦琐的异常处理。Optional类是用final修饰的,所以不能有子类。Optional类是带有泛型的类,所以该类可以保任何对象的值。

从Optional类的声明代码中就可以看出这些特性,JDK中的部分代码如下:

public final class Optional<T>(
      private final T value;
      .........             //省略其他代码
}

Optional类中有一个叫作value的成员属性,这个属性就是用来保存具体值的。value 是用泛型T修饰的,并且还用了final修饰,这表示一个Optional对象只能保存一个值。

Optional类提供的常用方法 

Collectors类

collectors类为收集器类,该类实现了java.util.Colleetor接口,可以将Stream流对象进行各种各样的封装、归集、分组等操作。同时,Collectors类还提供了很多实用的数据加工方法,如数据统计计算等.

collecctors类的方法 

 二   数据过滤

数据过滤就是在杂乱的数据中筛选出需要的数据,类似SQL语句中的WHERE关键字,给出一的条件,将符合条件的数据过滤并展示出来。

1.  filter()方法

filter()方法是Stream接口提供的过滤方法。该方法可以将lambda表达式作为参数,然后按照lambà表达式的逻辑过滤流中的元素。过滤出想要的流元素后,还需使用Stream提供的collect0方法按照指定方法重新封装。

 基于Employee 员工类实现:

找出年龄大于30的员工

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Dome{
	public static void main(String[] args) {
		//找出年龄大于30的员工
		List<Employee> list = Employee.GetEmpList();//先获取所有的员工测试信息
		Stream<Employee> stream = list.stream();//获取集合流对象
		stream = stream.filter(e->e.GetAge()>30);
		List<Employee> result = stream.collect(Collectors.toList());
		for(Employee emp:result) {
			System.out.println(emp);
		}
	}
}

 2.distinct()方法

distinct)方法是Stream接口提供的过滤方法。该方法可以去除流中的重复元素,效果与SQL语句中的DISTINCT关键字一样。

 

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class text {
	public static void main(String[] args) {
		List<Integer> list = new ArrayList<>();
		list.add(1);
		list.add(2);
		list.add(6);
		list.add(9);
		list.add(2);
		list.add(3);
		list.add(6);
		System.out.println("去重前:");
		System.out.println(list);
		List<Integer> result = list.stream().distinct().collect(Collectors.toList());
		System.out.println("去重后:");
		System.out.println(result);
		
		
	}
}

3.limit()方法 

limit()方法是Stream接口提供的方法,该方法可以获取流中前N个元素。

找出性别为女的前两名员工 

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Dome{
	public static void main(String[] args) {
		//找出性别为女的前两名员工
		List<Employee> list = Employee.GetEmpList();//先获取所有的员工测试信息
		Stream<Employee> stream = list.stream();//获取集合流对象
		stream=stream.filter(e->e.GetSex().equals("女")).limit(2);
		List<Employee> result = stream.collect(Collectors.toList());
		for(Employee emp:result) {
			System.out.println(emp);
		}
	}
}

 4.skip()方法

skip()方法是Stream接口提供的方法,该方法可以忽略流中的N个元素。

取出所有男员工,并忽略前两个。

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Dome{
	public static void main(String[] args) {
		//找出性别为女的前两名员工
		List<Employee> list = Employee.GetEmpList();//先获取所有的员工测试信息
		Stream<Employee> stream = list.stream();//获取集合流对象
		stream=stream.filter(e->e.GetSex().equals("男")).skip(2);
		List<Employee> result = stream.collect(Collectors.toList());
		for(Employee emp:result) {
		   System.out.println(emp);
		}
	}
}

//		List<Employee> list = Employee.GetEmpList();
		list.stream().filter(e->e.GetSex().equals("男")).skip(2).forEach(n->{
			System.out.println(n);
这段代码可以替代上述的主代码实现相同功能

 三   数据映射

数据的映射和过滤概念不同:过滤是在流中找到符合条件的元素,映射是在流中获得具体的数量Stream接口提供了map()方法用来实现数据映射,map()方法会按照参数中的函数逻辑获取新的对象,新的流对象中元素类型可能与旧流对象元素类型不相同。

 

 

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Dome{
	public static void main(String[] args) {
		//获取开发部的所有员工的名单
		List<Employee> list = Employee.GetEmpList();//先获取所有的员工测试信息
		Stream<Employee> stream = list.stream();//获取集合流对象
		stream=stream.filter(e->e.Getdept().equals("开发部"));
		Stream<String> names = stream.map(Employee::GetName);//获取集合流对象
		List<String> result = names.collect(Collectors.toList());
		for(String emp:result) {
		   System.out.println(emp);
		}
	}
}

 四   数据查找

1. allMatch()方法

allMatchO方法是Stream接口提供的方法,该方法会判断流中的元素是否全部符合某一条件,返回结果是boolean值。如果所有元素都符合条件则返回true,否则返回false。

【代码实列】 


import java.util.List;


public class Dome{
	public static void main(String[] args) {
		List<Employee> list = Employee.GetEmpList();//先获取所有的员工测试信息
		boolean result= list.stream().allMatch(n->n.GetAge()>25);
		System.out.println("所有员工是否都大于25岁:"+result);
		
	
		  
		 
		
	}
}

【运行结果】 

 2. anyMatch()方法

anyMatchO方法是Stream接口提供的方法,该方法会判断流中的元素是否有符合某一条件,只要有一个元素符合条件就返回true,如果没有元素符合条件才会返回false。

【代码实列】 


import java.util.List;


public class Dome{
	public static void main(String[] args) {
		List<Employee> list = Employee.GetEmpList();//先获取所有的员工测试信息
		boolean result= list.stream().anyMatch(n->n.GetAge()>=40);
		System.out.println("该公司员工是否有40或以上的工岁吗?:"+result);
	}
}

 【运行结果】

3. noneMatch()方法

noneMatch()方法是Stream接口提供的方法,该方法会判断流中的所有元素是否都不符合某一条件。这个方法的逻辑和allMatch()方法正好相反。 

【代码实列】 


import java.util.List;


public class Dome{
	public static void main(String[] args) {
		List<Employee> list = Employee.GetEmpList();//先获取所有的员工测试信息
		boolean result= list.stream().noneMatch(e->e.GetSalary()<2000);
		System.out.println("该公司员工是否不存在工资低于2000的员工?:"+result);
	}
}

 【运行结果】

  4. findFirst()方法

findFirst方法是Stream接口提供的方法,这个方法会返回符合条件的第一个元素。

 【代码实列】


import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;


public class Dome{
	public static void main(String[] args) {
		List<Employee> list = Employee.GetEmpList();//先获取所有的员工测试信息
		Stream<Employee> stream= list.stream().filter(e->e.GetAge()==21);
		Optional<Employee> e =stream.findFirst();
		System.out.println(e);
	}
} 

【运行结果】 

 五   数据收集

1.数据统计

数据统计不仅可以筛选出特殊元素,还可以对元素的属性进行统计计算。这种复杂的统计操作不是由Stream实现的,而是由Collectors收集器类实现的,收集器提供了非常丰富的API,有着强大的数据挖掘能力。

 

 

【代码实列】 


import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;


public class Dome{
	public static void main(String[] args) {
		List<Employee> list = Employee.GetEmpList();//先获取所有的员工测试信息
		//输出公司总人数
		long count = list.stream().collect(Collectors.counting());
		count = list.stream().count();
		System.out.println("公司总人数:"+count);
		//输出公司年龄最大的员工
		Optional<Employee> ageMax= list.stream().collect(Collectors.maxBy(Comparator.comparing(Employee::GetAge)));
		Employee oder = ageMax.get();
		System.out.println("公司年龄最大的员工是:");
		System.out.println(oder);
		//输出公司年龄最大的
		Optional<Employee> ageMin= list.stream().collect(Collectors.minBy(Comparator.comparing(Employee::GetAge)));
		Employee younger = ageMin.get();
		System.out.println("公司年龄最小的员工是:");
		System.out.println(younger);
		//输出公司的总薪资
		double sum = list.stream().collect(Collectors.summingDouble(Employee::GetSalary));
		System.out.println("公司的总薪资为:"+sum);
		//统计公司薪资的平均值
		double Avg = list.stream().collect(Collectors.averagingDouble(Employee::GetSalary));
		System.out.println("公司的平均薪资:"+Avg);
		System.out.println("-----------------------");
		java.util.DoubleSummaryStatistics s = list.stream().collect(Collectors.summarizingDouble(Employee::GetSalary));
		System.out.println("统计:拿薪资的人数:"+s.getCount()+" ");
		System.out.println("薪资总数:"+s.getSum()+" ");
		System.out.println("平均薪资:"+s.getAverage()+" ");
		System.out.println("最高薪资"+s.getMax()+" ");
		System.out.println("最低薪资"+s.getMin()+" ");
		System.out.println("-----------------------");
		String nameList = list.stream().map(Employee::GetName).collect(Collectors.joining("-"));
		System.out.println("公司员工名单如下:\n"+nameList);
		
   }
} 

【运行结果】 

 2.数据分组

😶‍🌫️😶‍🌫️😶‍🌫️数据分组就是将流中元素按照指定的条件分开保存,类似SQL语言中的“GROUPBY”关键字。分组之后的数据会按照不同的标签分别保存成一个集合,然后按照“键值”关系封装在Map对象中。数据分组有一级分组和多级分组两种场景,首先先来介绍一级分组。
一级分组,就是将所有数据按照一个条件进行归类。例如,学校有100个学生,这些学生分布在3个年级中。学生按照年级分成了3组,然后就不再细分了,这就属于一级分组。
Collectors类提供的groupingBy0方法就是用来进行分组的方法,方法参数是一个Function接口对象,收集器会按照指定的函数规则对数据进行分组。

 

 

一级分组:


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


public class Dome{
	public static void main(String[] args) {
		List<Employee> list = Employee.GetEmpList();//先获取所有的员工测试信息
		Map<String,List<Employee>> map = list.stream().collect(Collectors.groupingBy(Employee::Getdept));
		for(String key:map.keySet()) {
			System.out.println("【"+key+"】");
			List<Employee> deptList = map.get(key);
			for(Employee e:deptList) {
				System.out.println(e);
			}
		}
		
   }
} 

 

 二级分组:


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


public class Dome{
	public static void main(String[] args) {
		List<Employee> list = Employee.GetEmpList();//先获取所有的员工测试信息
		Map<String,Map<String,List<Employee>>> map1 = list.stream().
				collect(Collectors.groupingBy
						(Employee::Getdept,Collectors.
								groupingBy(Employee::GetSex)));
		
		for(String key1:map1.keySet()) {
			System.out.println("【"+key1+"】"+"部门员工共列表如下:");
			
			Map<String,List<Employee>> map2 = map1.get(key1);
			for(String key2:map2.keySet()) {
				System.out.println("\t【"+key2+"】"+"员工信息:");
				for(Employee e:map2.get(key2)) {
					System.out.println("\t\t"+e);
				}
			}
		}
		
   }
} 

 

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

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

相关文章

azure data studio SQL扩展插件开发笔记

node.js环境下拉取脚手架 npm install -g yo generator-azuredatastudio yo azuredatastudio 改代码 运行 调试扩展&#xff0c;在visual studio code中安装插件即可 然后visual studio code打开进行修改运行即可 image.png 运行后自动打开auzre data studio了&#xff0c; 下面…

深度学习9:简单理解生成对抗网络原理

目录 生成算法 生成对抗网络&#xff08;GAN&#xff09; “生成”部分 “对抗性”部分 GAN如何运作&#xff1f; 培训GAN的技巧&#xff1f; GAN代码示例 如何改善GAN&#xff1f; 结论 生成算法 您可以将生成算法分组到三个桶中的一个&#xff1a; 鉴于标签&#…

6. 使用python将多个Excel文件合并到同一个excel-附代码解析

【目录】 文章目录 6. 使用python将多个Excel文件合并到同一个excel-附代码解析1. 目标任务2. 结果展示3. 代码示例4. 代码解析4.1 导入库4.2 调用库的类、函数、变量语法4.3 os.listdir-返回目录中的文件名列表4.4 startswith-用于判断一个字符串是否以指定的前缀开头4.5 ends…

如何评估开源项目的活跃度和可持续性?

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

深度学习1.卷积神经网络-CNN

目录 卷积神经网络 – CNN CNN 解决了什么问题&#xff1f; 需要处理的数据量太大 保留图像特征 人类的视觉原理 卷积神经网络-CNN 的基本原理 卷积——提取特征 池化层&#xff08;下采样&#xff09;——数据降维&#xff0c;避免过拟合 全连接层——输出结果 CNN …

postgresql-字符函数

postgresql-字符函数 字符串连接字符与编码字符串长度大小写转换子串查找与替换截断与填充字符串格式化MD5 值字符串拆分字符串反转 字符串连接 concat(str, …)函数用于连接字符串&#xff0c;并且忽略其中的 NULL 参数&#xff1b;concat_ws(sep, str, …) 函数使用指定分隔…

小研究 - Java虚拟机内存管理(三)

Java 语言的面向对象&#xff0c;平台无关&#xff0c;安全&#xff0c;开发效率高等特点&#xff0c;使其在许多领域中得到了越来越广泛的应用。但是由于Java程序由于自身的局限性&#xff0c;使其无法应用于实时领域。由于垃圾收集器运行时将中断Java程序的运行&#xff0c;其…

【手写promise——基本功能、链式调用、promise.all、promise.race】

文章目录 前言一、前置知识二、实现基本功能二、实现链式调用三、实现Promise.all四、实现Promise.race总结 前言 关于动机&#xff0c;无论是在工作还是面试中&#xff0c;都会遇到Promise的相关使用和原理&#xff0c;手写Promise也有助于学习设计模式以及代码设计。 本文主…

9个python自动化脚本,PPT批量生成缩略图、添加图片、重命名

引言 最近一番在整理资料&#xff0c;之前买的PPT资源很大很多&#xff0c;但归类并不好&#xff0c;于是一番准备把这些PPT资源重新整理一下。统计了下&#xff0c;这些PPT资源大概有2000多个&#xff0c;一共30多G&#xff0c;一个一个手动整理这个投入产出比也太低了。 作为…

CotEditor for mac 4.0.1 中文版(开源文本编辑器)

coteditorformac是一款简单实用的基于Cocoa的macOS纯文本编辑器&#xff0c;coteditormac版本可以用来编辑网页、结构化文本、程序源代码等文本文件&#xff0c;使用起来非常方便。 CotEditor for Mac具有正则表达式搜索和替换、语法高亮、编码等实用功能&#xff0c;而CotEdi…

QtWidgets和QtQuick融合(QML与C++融合)

先放一个界面效果吧&#xff01; 说明&#xff1a;该演示程序为一个App管理程序&#xff0c;可以将多个App进行吸入管理。 &#xff08;动画中的RedRect为一个带有QSplashScreen的独立应用程序&#xff09; 左侧边栏用的是QQuickView进行.qml文件的加载&#xff08;即QtQuick…

JS算法之树(一)

前言 之前我们已经介绍过一种非顺序数据结构&#xff0c;是散列表。 JavaScript散列表及其扩展http://t.csdn.cn/RliQf 还有另外一种非顺序数据结构---树。 树数据结构 树是一种分层数据的抽象模型。公司组织架构图就是常见的树的例子。 相关术语 一个树结构&#xff0…

x86的内存寻址方式

文章目录 一、实模式寻址二、保护模式寻址三、段页式内存管理四、Linux的内存寻址五、进程与内存1、内核空间和用户空间2、内存映射3、进程内存分配与回收 一、实模式寻址 在16位的8086时代&#xff0c;CPU为了能寻址超过16位地址能表示的最大空间&#xff08;因为 8086 的地址…

小研究 - J2EE 应用服务器的软件老化测试研究

软件老化现象是影响软件可靠性的重要因素&#xff0c;长期运行的软件系统存在软件老化现象&#xff0c;这将影响整个业务系统的正常运行&#xff0c;给企事业单位带来无可估量的经济损失。软件老化出现的主要原因是操作系统资源消耗殆尽&#xff0c;导致应用系统的性能下降甚至…

virtuoso61x中集成calibre

以virtuoso618为例&#xff0c;在搭建完电路、完成前仿工作之后绘制版图&#xff0c;版图绘制完成之后需要进行drc和lvs【仅对于学校内部通常的模拟后端流程而言】&#xff0c;一般采用mentor的calibre来完成drc和lvs。 服务器上安装有virtuoso和calibre&#xff0c;但是打开la…

servlet,Filter,责任的设计模式,静态代理

servlet servlet是前端和数据库交互的一个桥梁 静态网页资源的技术&#xff1a;在前端整个运行的过程中 我们的网页代码不发生改变的这种情况就称为静态的网页资源技术动态网页资源的技术&#xff1a;在前端运行的过程中 我们的前端页面代码会发生改变的这种情况就称为 动态的网…

电商版面设计之优惠券设计

1、画一个矩形---最快的方法&#xff0c;提前写好 2、ALT复制矩形图层 3、提前把优惠券的文案准备好 4、改一下字体---72 5、字体改成12号字体 6、上面对齐选择第二个去做&#xff0c;最上方 7、后面那个就是门槛 8、用Alt复制4个 9、改字就行 10、看见不错的优惠劵设计可以参…

word如何调整页码

文章目录 如何调整页码 如何调整页码 用 word 写报告的时候&#xff0c;经常遇到要求说是要从正文开始才显示页码&#xff0c;那如何实现呢 把鼠标放在我们正文的那一页的顶部&#xff0c;点击 布局 ,再点击分隔符&#xff0c;再点击连续 再点击编译页脚 选择你想要的页脚格式…

十四、pikachu之XSS

文章目录 1、XSS概述2、实战2.1 反射型XSS&#xff08;get&#xff09;2.2 反射型XSS&#xff08;POST型&#xff09;2.3 存储型XSS2.4 DOM型XSS2.5 DOM型XSS-X2.6 XSS之盲打2.7 XSS之过滤2.8 XSS之htmlspecialchars2.9 XSS之href输出2.10 XSS之JS输出 1、XSS概述 Cross-Site S…

探讨uniapp的组件使用的问题

1 view Flex是Flexible Box的缩写&#xff0c;意为“弹性布局”&#xff0c;用来为盒状模型提供最大的灵活性。 当设置display: flex后&#xff0c;继续给view等容器组件设置flex-direction:row或column&#xff0c;就可以在该容器内按行或列排布子组件。uni-app推荐使用flex布…