首页 > 编程语言 >零基础学Java第二十六天之Stream流

零基础学Java第二十六天之Stream流

时间:2024-05-29 14:00:46浏览次数:28  
标签:第二十六 Java Stream stream System Course Student println new

Stream

简介

Stream(流)是数据渠道,用于操作数据源(集合、数组等),生成元素序列。换言之,集合是存储数据的容器,流使用操作这些数据的

Stream可以对集合进行非常复杂的查找、过滤、映射数据等操作,类似于SQL执行数据库查询。Stream提供了一种高效且易于使用的处理数据的方式

注意:

  • Stream不会存储数据
  • Stream不会改变源数据,通过一系列操作数据源会返回一个持有结果的新Stream
  • Stream操作是延迟执行的,意味着流会等到需要结果的时候才执行
执行步骤
  1. 创建Stream:通过数据源(集合、数组等)获取一个Stream
  2. 中间操作:中间操作链,对源数据的数据进行处理
  3. 终止操作:执行中间操作,并产生结果
创建Stream
public class Test1 {
	@Test
	public void test01() {
		//方式一:通过Collection接口提供的stream()-串行流或parallelStream()-并行流 获取流对象
		List<String> list = new ArrayList<>();
		Stream<String> stream1 = list.stream();
		
		//方式二:通过Arrays的静态方法stream()获取流对象
		String[] strs = new String[10];
		Stream<String> stream2 = Arrays.stream(strs);
		
		//方式三:通过Stream的静态方法of()获取流对象
		Stream<String> stream3 = Stream.of("aaa","bbb","ccc");
		
		//方式四:创建无限流
		//iterate()迭代
		Stream<Integer> stream4 = Stream.iterate(1, (x)->x+=100);
		stream4.limit(3).forEach(System.out::println);
		
        //方式五:创建无限流
		//generate()生成
		Stream<Double> stream5 = Stream.generate(()->Math.random());
		stream5.limit(3).forEach(System.out::println);
	}
}

注意:多个中间操作可以连接成一个流水线,除非流水线触发终止操作,否则中间操作不会执行任何的处理,而在终止操作时一次性全部处理,称为惰性求值/延迟加载

中间操作 - 筛选与切片
方法描述
filter(Predicate p)从流中排除元素
limit(long maxSize)设置限制数据条数
skip(long n)跳过元素,返回跳过n个元素的流,若流中不满足n个元素则返回空流。与limit()互补
distinct()筛选,流通过元素对象的hashCode()和equals()方法去除重复元素

如果没有终止操作,中间操作就不会被调用,终止操作时一次性全部处理,这种称为惰性求值/延迟加载

public class Test1 {
	List<Student> stuList = Arrays.asList(
			new Student("张三", 28, 4800,Course.JAVA),
			new Student("李四", 36, 7200,Course.JAVA),
			new Student("王五", 19, 9600,Course.HTML),
			new Student("赵六", 42, 6100,Course.HTML),
			new Student("孙七", 23, 9600,Course.PYTHON),
			new Student("吴八", 31, 3000,Course.PYTHON),
   			new Student("李四", 36, 7200,Course.JAVA));
	@Test
	public void test01() {	
		//需求1:过滤掉小于5000的学生对象
		Stream<Student> stream = stuList.stream().filter((x)-> {
			System.out.println("中间操作");
			return x.getSalary()>5000;
		});
		//迭代输出流里的数据就等同于终止操作
		//迭代功能在forEach()中完成,称为内部迭代(集合使用iterator()称为外部迭代)
		stream.forEach(System.out::println);
	}
	@Test
	public void test02() {	
		//需求2:过滤掉小于5000的学生对象,并显示3条
		//注意:因为限制了数据条数,所以满足数据条数后,后续的操作就不再运行了,效率就提高了
		Stream<Student> stream = stuList.stream().filter((x)-> {
			System.out.println("短路");
			return x.getSalary()>5000;
		}).limit(3);
		//迭代输出流里的数据就等同于终止操作
		//迭代功能在forEach()中完成,称为内部迭代(集合使用iterator()称为外部迭代)
		stream.forEach(System.out::println);
	}
	@Test
	public void test03() {	
		//需求3:过滤掉小于5000的学生对象,并跳过第1个学生对象
		Stream<Student> stream = stuList.stream().
				filter((x)-> x.getSalary()>5000).
				skip(1);
		//迭代输出流里的数据就等同于终止操作
		//迭代功能在forEach()中完成,称为内部迭代(集合使用iterator()称为外部迭代)
		stream.forEach(System.out::println);
	}
	@Test
	public void test04() {	
		//需求4:过滤掉小于5000的学生对象,并筛选掉重复元素
        //Stream底层通过元素对象(Student对象)的hashCode()和equals()方法去除重复元素
		Stream<Student> stream = stuList.stream().
				filter((x)-> x.getSalary()>5000).
				distinct();

		//迭代输出流里的数据就等同于终止操作
		//迭代功能在forEach()中完成,称为内部迭代(集合使用iterator()称为外部迭代)
		stream.forEach(System.out::println);
	}
}
enum Course{//课程枚举
	JAVA,HTML,PYTHON;
}
class Student{//学生类
	private String name;
	private int age;
	private double salary;
	private Course course;
    ...
}
中间操作 - 映射
方法描述
map(Function<?, ? > mapper)将流中所有元素映射成一个新的元素或者提取信息
flatMap(Function<?, ? extends Stream<? >> mapper)将流中的流整合(整合成平面/平铺流)
public class Test1 {

	List<String> nameList = Arrays.asList("张三","李四","王五","赵六","孙七","吴八");	
	List<Student> stuList = Arrays.asList(
			new Student("张三", 28, 4800,Course.JAVA),
			new Student("李四", 36, 7200,Course.JAVA),
			new Student("王五", 19, 9600,Course.HTML),
			new Student("赵六", 42, 6100,Course.HTML),
			new Student("孙七", 23, 9600,Course.PYTHON),
			new Student("吴八", 31, 3000,Course.PYTHON),
			new Student("李四", 36, 7200,Course.JAVA));
	@Test
	public void test01() {	
		//map() - 将流中所有元素映射成一个新的元素 或者 提取信息
        
		//方式1:映射成一个新的元素
        //需求:将流中所有字符串拼接成新的字符串
		nameList.stream().map((str)-> str.charAt(0)).forEach(System.out::println);
		
        //方式2:映射成提取信息
        //需求:把原来流中的学生对象替换成学生姓名
		stuList.stream().map((stu)-> stu.getName()).forEach(System.out::println);
	}
	@Test
	public void test02() {	
		//带着需求学flatMap()
		//flatMap() - 将流中的流整合(整合成平面/平铺流)
		//需求:将nameList里的字符串转换为字符输出

		//解决方案1:使用map()完成需求,可以看到流里包含另外的流,非常麻烦
		Stream<Stream<Character>> stream = nameList.stream().
				map(Test1::getCharacterStream);//{{'张','三'},{'李','四'},...}
		stream.forEach((sm) -> {
			sm.forEach(System.out::println);
		});
       
		//解决方案2:使用flatMap()完成需求,将流中的流一并整合
		nameList.stream().flatMap((str)-> getCharacterStream(str)).
		forEach(System.out::println);//{'张','三'},{'李','四'},...
	}
	//将字符串拆分出字符转换为流的方法
	public static Stream<Character> getCharacterStream(String str){//"张三"
		
        ArrayList<Character> list = new ArrayList<>();//'张','三'

		for (Character c : str.toCharArray()) {
			list.add(c);
		}
		return list.stream();
	}
}
enum Course{//课程枚举
	JAVA,HTML,PYTHON;
}
class Student{//学生类
	private String name;
	private int age;
	private double salary;
	private Course course;
    ...
}
中间操作 - 排序
方法解释
sorted()使用元素原有排序规则 - Comparable
sorted(Comparator<? super T> comparator)使用自定义排序规则 - Comparator
public class Test1 {
	List<Student> stuList = Arrays.asList(
			new Student("张三", 28, 4800,Course.JAVA),
			new Student("李四", 36, 7200,Course.JAVA),
			new Student("王五", 19, 9600,Course.HTML),
			new Student("赵六", 42, 6100,Course.HTML),
			new Student("孙七", 23, 9600,Course.PYTHON),
			new Student("吴八", 31, 3000,Course.PYTHON),
			new Student("吴八", 31, 3000,Course.PYTHON));
	@Test
	public void test01() {	
        //使用元素原有排序规则(Comparable<T>)
        //需求:按照年龄排序
		stuList.stream().sorted().forEach(System.out::println);
	}
	@Test
	public void test02() {	
		//使用自定义排序规则(Comparator<T>)
        //需求:按照工资排序
		stuList.stream().sorted((e1,e2)->{
			if(e1.getSalary() == e2.getSalary()){
				return 1;
			}
			return (int)(e1.getSalary() - e2.getSalary());
		}).forEach(System.out::println);	
	}
}
enum Course{//课程枚举
	JAVA,HTML,PYTHON;
}
class Student implements Comparable<Student>{//学生类
	private String name;
	private int age;
	private double salary;
    ...
}
终止操作 - 匹配与查找
方法描述
allMatch(Predicate<? super T> predicate)检查是否匹配所有元素
anyMatch(Predicate<? super T> predicate)检查是否匹配至少一个元素
noneMatch(Predicate<? super T> predicate)检查是否没有匹配所有元素
findFirst()返回第一个元素
findAny()返回任意一个元素(但效果不好)
count()返回流中元素的个数
max(Comparator<? super T> comparator)返回流中最大值
min(Comparator<? super T> comparator)返回流中最小值
public class Test1 {
	List<Student> stuList = Arrays.asList(
			new Student("张三", 28, 4800,Course.JAVA),
			new Student("李四", 36, 7200,Course.JAVA),
			new Student("王五", 19, 9600,Course.HTML),
			new Student("赵六", 42, 6100,Course.HTML),
			new Student("孙七", 23, 9600,Course.PYTHON),
			new Student("吴八", 31, 3000,Course.PYTHON),
			new Student("吴八", 31, 3000,Course.PYTHON));
	@Test
	public void test01() {	
		//需求1:检查流中所有元素是否匹配 工资>5000
		boolean allMatch = stuList.stream().allMatch((stu) -> stu.getSalary()>5000);
		System.out.println(allMatch);//false
	
		//需求2:检查流中所有元素至少匹配一个 工资>5000
		boolean  anyMatch = stuList.stream().anyMatch((stu) -> stu.getSalary()>5000);
		System.out.println(anyMatch);//true
        
        //需求3:检查流中所有元素是否没有匹配 工资>5000
		boolean noneMatch = stuList.stream().noneMatch((stu) -> 				
                stu.getSalary()>5000);
		System.out.println(noneMatch);
        
        //需求4:返回工资最高的学生信息
		Optional<Student> findFirst = stuList.stream().
				sorted((stu1,stu2)->Double.compare(
                    stu1.getSalary(),stu2.getSalary())).
				findFirst();
		Student stu = findFirst.get();
		//这种写法防止NullPointerException出现
		//Student stu = findFirst.orElse(new Student());
		System.out.println(stu);
        
        //需求5:返回随机学生信息(但效果不好)
		Optional<Student> findAny = stuList.stream().findAny();
		Student stu = findAny.get();
		System.out.println(stu);
        
       //需求6:获取学生个数
		long count = stuList.stream().count();
		System.out.println(count);
        
        //需求7:获取最高工资的学生信息
		Optional<Student> max = stuList.stream().
				max((stu1,stu2)->Double.compare(stu1.getSalary(),stu2.getSalary()));
		System.out.println(max.get());
        
       //需求8:获取最低工资的学生信息
		Optional<Student> min = stuList.stream().
				min((stu1,stu2)->Double.compare(stu1.getSalary(),stu2.getSalary()));
		System.out.println(min.get());
	}
}
enum Course{//课程枚举
	JAVA,HTML,PYTHON;
}
class Student implements Comparable<Student>{//学生类
	private String name;
	private int age;
	private double salary;
	private Course course;
   	...
}
终止操作 - 归约

归约:将流中的元素反复结合起来,得到一个值

map+reduce的连接通常称为map_reduce模式,因Google用它进行网络搜索而出名

方法描述
reduce( T identity , BinaryOperator accumulator)参数:(初始值,结合逻辑)
reduce(BinaryOperator accumulator)参数:(结合逻辑)
public class Test1 {

	List<Integer> numList = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
	List<Student> stuList = Arrays.asList(
			new Student("张三", 28, 4800,Course.JAVA),
			new Student("李四", 36, 7200,Course.JAVA),
			new Student("王五", 19, 9600,Course.HTML),
			new Student("赵六", 42, 6100,Course.HTML),
			new Student("孙七", 23, 9600,Course.PYTHON),
			new Student("吴八", 31, 3000,Course.PYTHON),
			new Student("李四", 36, 7200,Course.JAVA));
	@Test
	public void test01() {	
		//需求:获取numList集合中元素的总和
		Integer reduce = numList.stream().
				reduce(0, (x,y)->x+y);
		System.out.println(reduce);
	}
	@Test
	public void test02() {	
		//需求:获取stuList集合中所有学生工资总和
		Optional<Double> reduce = stuList.stream().
				map(Student::getSalary).reduce(Double::sum);
		Double sumSalary = reduce.get();
		System.out.println(sumSalary);
	}
}
enum Course{//课程枚举
	JAVA,HTML,PYTHON;
}
class Student implements Comparable<Student>{//学生类
	private String name;
	private int age;
	private double salary;
	private Course course;
终止操作 - 收集

收集:将流转换为其他形式。接收一个Collector接口的实现,用于给Stream中元素做汇总的方法

方法描述
collect(Collector<? super T, A, R> collector)把元素放入Collector集合中
public class Test1 {

	List<Student> stuList = Arrays.asList(
			new Student("张三", 28, 4800,Course.JAVA),
			new Student("李四", 36, 7200,Course.JAVA),
			new Student("王五", 19, 9600,Course.HTML),
			new Student("赵六", 42, 6100,Course.HTML),
			new Student("孙七", 23, 9600,Course.PYTHON),
			new Student("吴八", 31, 3000,Course.PYTHON),
			new Student("李四", 36, 7200,Course.JAVA));

	@Test
	public void test01() {
		//把数据收集到集合中
		
		//需求1:把当前学生姓名提取出来,并把数据放入List集合中
		List<String> list = stuList.stream().
				map(Student::getName).
				collect(Collectors.toList());
		list.forEach(System.out::println);

		//需求2:把当前学生姓名提取出来,并把数据放入Set集合中
		Set<String> set = stuList.stream().
				map(Student::getName).collect(Collectors.toSet());
		set.forEach(System.out::println);

		//需求3:把当前学生姓名提取出来,并把数据放入指定集合中
		HashSet<String> hashSet = stuList.stream().
			map(Student::getName).collect(Collectors.toCollection(HashSet::new));
		hashSet.forEach(System.out::println);
	}	
	@Test
	public void test02() {
		//收集流中的各种数据
		
		//需求1:收集/获取学生个数
		Long count = stuList.stream().
				map(Student::getName).collect(Collectors.counting());
		System.out.println(count);

		//需求2:收集/获取学生平均工资
		Double avg = stuList.stream().
				collect(Collectors.averagingDouble(Student::getSalary));
		System.out.println(avg);

		//需求3:收集/获取学生总工资
		Double sum = stuList.stream().
				collect(Collectors.summingDouble(Student::getSalary));
		System.out.println(sum);

		//需求4:收集/获取学生工资最大值
		Optional<Double> max = stuList.stream().map(Student::getSalary).
				collect(Collectors.maxBy(Double::compareTo));
		System.out.println(max.get());

		//需求5:收集/获取学生工资最小值
		Optional<Double> min = stuList.stream().map(Student::getSalary).
				collect(Collectors.minBy(Double::compareTo));
		System.out.println(min.get());

		//需求6:收集/获取工资最多的学生信息
		Optional<Student> maxStu = stuList.stream().
				collect(Collectors.maxBy(
						(stu1,stu2)-> (int)(stu1.getSalary()-stu2.getSalary())));
		System.out.println(maxStu.get());

		//需求7:收集/获取工资最少的学生信息
		Optional<Student> minStu = stuList.stream().
				collect(Collectors.minBy(
                    (stu1,stu2)-> (int)(stu1.getSalary()-stu2.getSalary())));
		System.out.println(minStu.get());
	}	
	@Test
	public void test03() {//分组
		//需求:按照学科分组
		Map<Course, List<Student>> map = stuList.stream().collect(
            Collectors.groupingBy(Student::getCourse));
		System.out.println(map);
	}
	@Test
	public void test04() {//多级分组
		//需求:按照学科分组,在按照年龄分组
		Map<Course, Map<String, List<Student>>> map = stuList.stream().
				collect(Collectors.groupingBy(
						Student::getCourse,Collectors.groupingBy((stu)->{
							if(((Student)stu).getAge() < 28){
								return "青年";
							}else if(((Student)stu).getAge() < 40){
								return "中年";
							}else{
								return "老年";
							}
						})));
		System.out.println(map);
	}
    @Test
	public void test05() {//分区
        //需求:按照工资5000为标准分区
		Map<Boolean, List<Student>> map = stuList.stream().collect(
				Collectors.partitioningBy((stu) -> stu.getSalary()>5000));
		System.out.println(map);
	}
    @Test
	public void test06() {//获取元素中字段的各种信息
		//需求:获取学生工资信息,再获取总值、平均值、最大值、最小值
		DoubleSummaryStatistics collect = stuList.stream().collect(
				Collectors.summarizingDouble(Student::getSalary));
		System.out.println(collect.getSum());
		System.out.println(collect.getAverage());	
		System.out.println(collect.getMax());
		System.out.println(collect.getMin());
	}
    @Test
	public void test07() {//拼接信息
		//需求:拼接学生姓名
		String str1 = stuList.stream().map(Student::getName).collect(
				Collectors.joining());
		System.out.println(str1);
		
		String str2 = stuList.stream().map(Student::getName).collect(
				Collectors.joining(","));
		System.out.println(str2);
		
		String str3 = stuList.stream().map(Student::getName).collect(
				Collectors.joining(",","--","--"));
		System.out.println(str3);
	}
}
enum Course{//课程枚举
	JAVA,HTML,PYTHON;
}
class Student implements Comparable<Student>{//学生类
	private String name;
	private int age;
	private double salary;
	private Course course;
    ...
}

标签:第二十六,Java,Stream,stream,System,Course,Student,println,new
From: https://blog.csdn.net/qq_53720725/article/details/139294048

相关文章

  • 采用Java+ SpringBoot+ IntelliJ+idea开发的ADR药物不良反应监测系统源码
    采用Java+SpringBoot+IntelliJ+idea开发的ADR药物不良反应监测系统源码ADR药物不良反应监测系统有哪些应用场景?ADR药物不良反应监测系统有哪些应用场景?ADR药物不良反应监测系统具有广泛的应用场景,以下是一些主要的应用场景:一、医院临床监测:药品不良反应智能监测系统基......
  • 基于Java+Vue的园区智能化管理系统:优化园区工作流程,夯实园区服务和管理水平(整套源码)
        前言:智慧园区管理平台是一个集成了多种功能的综合性系统,旨在通过信息化、智能化手段提升园区的管理效率和服务质量。以下是针对系统的各个功能模块的简要描述:一、楼栋管理会务管理:管理园区内的会议预约、会议室使用等。园区信息:展示园区的基本信息,如位置、面积、规......
  • JavaScript基础ECMAScript知识点复习整理
    **本篇文章食用的简单说明**本篇文章为复习JavaScript基础ECMAScript进行了知识点梳理,加粗部分为重点!!!加粗加红为重重点!!!由于JavaScript内容比较多,本篇文章只是基础部分,WebAPIs(DOM和BOM)等知识在后续过程中会继续更新,欢迎小伙伴在评论区补充~推荐大家按记忆梳理部分的内容自......
  • Java实战开发第一课-接口设计
    1、协议协议通常采用HTTP查询类接口通常为get或者post(查询条件较少用get,较多用post)还需要确定content-type,参数以哪种数据格式提交,结果通过哪种数据格式响应大多数以json格式响应2、分析请求参数根据请求参数定义模型类3、分析响应结果根据响应结果定义模型类4、使......
  • 简单了解java接口
    java中接口的定义与实现接口的作用制定规则制定规则的两种方案定义类:类中书写抽象方法(不建议使用,因为类只能单一继承)定义接口:接口中书写抽象方法(建议使用,因为接口可以实现多继承)接口的定义publicinterface接口名子{//抽象方法}注意:接口不能实例化,即接口不......
  • java代码块
    Java中的代码块代码块分类静态代码块构造代码块局部代码块构造代码块怎么书写构造代码块publicclassDemo{{//构造代码块,书写位置是类中方法外}}构造代码块执行特点和作用执行特点:会在每一个构造方法执行前执行一次publicclassDemo......
  • java是什么?
    一、Java基础Java语言特性面向对象:Java是一种面向对象的编程语言,支持封装、继承和多态等OOP概念。跨平台性:Java程序通过Java虚拟机(JVM)实现跨平台运行。简单性:相较于C++,Java摒弃了复杂的指针和多重继承等概念,使学习更加容易。安全性:Java提供了丰富的安全特性,如内存管理和垃圾......
  • 【Java】流程控制(条件语句、循环语句、分支语句和异常处理)
    1、简介流程控制是编程中非常重要的一部分,它决定了程序执行的顺序和逻辑。在Java中,有几种主要的流程控制结构,包括条件语句、循环语句、分支语句和异常处理。2、条件语句2.1简介条件语句用于根据某个条件是否成立来决定执行哪段代码。Java中最常用的条件语句是if语句,if-els......
  • 【Java】运算符
    1、简介在Java中,运算符是用于执行特定操作的符号。它们可以用于各种数据类型,并执行如算术运算、比较、逻辑运算、位运算以及赋值等操作。2、算术运算符2.1内容算术运算符用于执行常见的数学运算。+:加法-:减法*:乘法/:除法%:取余(模运算)++:自增(前置和后置)--:自减(前置和后置) 2.2......
  • Java中的G1GC是如何工作的.18219565
    原文:HowG1GarbageCollectorworkinJava作者:PerspectiveMentorG1垃圾收集器采用了一个全新的垃圾收集方式,这让它在Java中的其它GC算法中鹤立鸡群。介绍G1(Garbage-First)是作为Parallel和CMS的替代者被引入到Java中的。它的设计目标是提供更加可预测的程序暂停时间,同时......