java8新特性-stream2

商皓
2023-12-01

终止操作

                          allMatch——检查是否匹配所有元素
 anyMatch——检查是否至少匹配一个元素
 noneMatch——检查是否没有匹配的元素
 findFirst——返回第一个元素
 findAny——返回当前流中的任意元素
 count——返回流中元素的总个数
 max——返回流中最大值

 min——返回流中最小值

List<Student> list=Arrays.asList(
			new Student("里斯", 12, "男"),
			new Student("刘丽", 11, "女"),
			new Student("刘星", 22, "女"),
			new Student("菜鸡", 42, "女"),
			new Student("菜鸡", 42, "女"),
			new Student("王五", 75, "男"));
	
	@Test
	public void test(){
		boolean allMatch = list.stream().allMatch((e)->e.getAge()>20);
		System.out.println(allMatch);
		boolean anyMatch = list.stream().anyMatch((e)->e.getAge()>20);
		System.out.println(anyMatch);
		boolean noneMatch = list.stream().noneMatch((e)->e.getAge()>330);
		System.out.println(noneMatch);
		Optional<Student> findFirst = list.stream().findFirst();
		System.out.println(findFirst.get());
		Optional<Student> findAny = list.stream().findAny();
		System.out.println(findAny.get());
		long count = list.stream().count();
		System.out.println(count);
		System.out.println("================");
		Optional<Student> max = list.stream().max((e1,e2)->Integer.compare(e1.getAge(), e2.getAge()));
		System.out.println(max.get());
		Optional<Integer> min = list.stream().map((e)->e.getAge()).min((e1,e2)->Integer.compare(e1, e2));
		System.out.println(min.get());
	}

归约

reduce(T identity, BinaryOperator) / reduce(BinaryOperator) ——可以将流中元素反复结合起来,得到一个值。

List<Student> list=Arrays.asList(
			new Student("里斯", 12, "男",88.09),
			new Student("刘丽", 11, "女",28.09),
			new Student("刘星", 22, "女",78.09),
			new Student("菜鸡", 42, "女",98.09),
			new Student("菜鸡", 42, "女",83.09),
			new Student("王五", 75, "男",84.09));
	@Test
	public void tets01(){
		Optional<Integer> reduce = list.stream().map(Student::getAge).reduce((x,y)->x+y);
		System.out.println(reduce.get());//204
		System.out.println("================");
		Integer reduce2 = list.stream().map(Student::getAge).reduce(0,(x,y)->x+y);
		//因有起始值所以这段代码返回值为Integer,Optional为避免为null
		System.out.println(reduce2);//204
	}

收集

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

@Test
	public void test02(){
		Object[] array = list.stream().map(Student::getName).toArray();
		for (Object object : array) {
			System.out.println(object);
		}
		 System.out.println("================");
		 List<String> collect = list.stream().map(Student::getName).collect(Collectors.toList());
	     collect.forEach(System.out::println);//里斯 刘丽   刘星 菜鸡 菜鸡 王五
	     System.out.println("================");
	     Set<String> collect2 = list.stream().map(Student::getName).collect(Collectors.toSet());
	     collect2.forEach(System.out::println);//里斯 刘丽   刘星  菜鸡 王五
	}
	
	@Test
	public void test03(){
		Long collect = list.stream().map(Student::getAge).collect(Collectors.counting());
		System.out.println(collect);//6
		System.out.println("================");
		Optional<Integer> collect2 = list.stream().map(Student::getAge).collect(Collectors.maxBy((x,y)->Integer.compare(x, y)));
		System.out.println(collect2.get());//75
		System.out.println("================");
		Optional<Double> collect3 = list.stream().map(Student::getScore).collect(Collectors.minBy((e1, e2) -> Double.compare(e1, e2)));
		System.out.println(collect3.get());//28.09
		System.out.println("================");
		Double collect4 = list.stream().collect(Collectors.averagingDouble(Student::getAge));
		System.out.println(collect4);//34.0
	}
	@Test
	public void test04(){
		DoubleSummaryStatistics collect = list.stream().collect(Collectors.summarizingDouble(Student::getScore));
		System.out.println(collect.getAverage());//76.59
		System.out.println(collect.getMax());//98.09
		System.out.println(collect.getMin());//28.09
	}
	
	//分组
	@Test
	public void test05(){
		Map<String, List<Student>> collect = list.stream().collect(Collectors.groupingBy(Student::getName));
		System.out.println(collect);
		//{里斯=[Student [name=里斯, age=12, sex=男, score=88.09]], 菜鸡=[Student [name=菜鸡, age=42, sex=女, score=98.09], Student [name=菜鸡, age=42, sex=女, score=83.09]], 
		//王五=[Student [name=王五, age=75, sex=男, score=84.09]], 刘星=[Student [name=刘星, age=22, sex=女, score=78.09]], 刘丽=[Student [name=刘丽, age=11, sex=女, score=28.09]]}
	}
	   //分组之后的操作
		@Test
		public void test06(){
		Map<String, Long> collect = list.stream().collect(Collectors.groupingBy(Student::getSex, Collectors.counting()));
		System.out.println(collect);//{女=4, 男=2}  是不是这个时候觉得跟sql一样牛逼了
		Map<String, Double> collect2 = list.stream().collect(Collectors.groupingBy(Student::getSex, Collectors.averagingInt(Student::getAge)));
		System.out.println(collect2);//{女=29.25, 男=43.5}
		List<Student> lists=Arrays.asList(
				new Student("里斯", 12, "男",88.09),
				new Student("刘丽", 22, "女",28.09),
				new Student("刘星", 22, "女",78.09),
				new Student("菜鸡", 42, "女",98.09),
				new Student("菜鸡", 42, "女",83.09),
				new Student("王五", 75, "男",84.09));
		Map<String, Map<Integer, List<Student>>> collect3 = lists.stream().collect(Collectors.groupingBy(Student::getSex, Collectors.groupingBy(Student::getAge)));
		System.out.println(collect3);
		/**
		 * {女={22=[Student [name=刘丽, age=22, sex=女, score=28.09], Student [name=刘星, age=22, sex=女, score=78.09]],
		 *  42=[Student [name=菜鸡, age=42, sex=女, score=98.09], Student [name=菜鸡, age=42, sex=女, score=83.09]]}, 
		 * 男={75=[Student [name=王五, age=75, sex=男, score=84.09]], 12=[Student [name=里斯, age=12, sex=男, score=88.09]]}}
		 */
	   Map<String, Map<String, List<Student>>> collect5 = lists.stream().collect(Collectors.groupingBy(Student::getSex, Collectors.groupingBy((e)->{
		 if(e.getScore()>=60){
			 return "及格";
		 }else if(e.getScore()<60){
			 return "不及格";
		 }else if(e.getScore()>90){
			 return "优秀";
		 }else{
			 return "一般";
		 }
	    })));
		System.out.println(collect5);
		/**
		 * {
		 *  女={不及格=[Student [name=刘丽, age=22, sex=女, score=28.09]], 及格=[Student [name=刘星, age=22, sex=女, score=78.09], Student [name=菜鸡, age=42, sex=女, score=98.09], Student [name=菜鸡, age=42, sex=女, score=83.09]]},
		 *  男={及格=[Student [name=里斯, age=12, sex=男, score=88.09], Student [name=王五, age=75, sex=男, score=84.09]]}
		 *  }
		 */
		}
		
		//分区
	@Test	
	 public void test07(){
		Map<Boolean, List<Student>> collect = list.stream().collect(Collectors.partitioningBy((e)->e.getAge()>29));
		System.out.println(collect);
		/**
		 * {
		 * false=[Student [name=里斯, age=12, sex=男, score=88.09], Student [name=刘丽, age=11, sex=女, score=28.09], Student [name=刘星, age=22, sex=女, score=78.09]], 
		 * true=[Student [name=菜鸡, age=42, sex=女, score=98.09], Student [name=菜鸡, age=42, sex=女, score=83.09], Student [name=王五, age=75, sex=男, score=84.09]]
		 * }
		 */
	 }	
	@Test	
	 public void test08(){
		String collect = list.stream().map(Student::getName).collect(Collectors.joining());
		System.out.println(collect);//里斯刘丽刘星菜鸡菜鸡王五
		String collect2 = list.stream().map(Student::getName).collect(Collectors.joining(","));
		System.out.println(collect2);//里斯,刘丽,刘星,菜鸡,菜鸡,王五
		String collect3 = list.stream().map(Student::getName).collect(Collectors.joining(",","<<<<",">>>>"));
		System.out.println(collect3);//里斯,刘丽,刘星,菜鸡,菜鸡,王五
	}	

============stream并行流==============

jdk1.7 有多线程处理框架 Fork join ,可以用于数据的并行操作,缺点:代码比较多,理解较难

Fork join  可以看这篇文章点击打开链接


计算1-10000000000L的累加

新建ForkJoinCalculate

import java.util.concurrent.RecursiveTask;
public class ForkJoinCalculate extends RecursiveTask<Long>{

	/**
	 * 
	 */
	private static final long serialVersionUID = 13475679780L;
	
	private long start;
	private long end;
	
	private static final long THRESHOLD = 10000L; //临界值
	
	public ForkJoinCalculate(long start, long end) {
		this.start = start;
		this.end = end;
	}
	
	@Override
	protected Long compute() {
		long length = end - start;
		
		if(length <= THRESHOLD){
			long sum = 0;
			
			for (long i = start; i <= end; i++) {
				sum += i;
			}
			
			return sum;
		}else{
			long middle = (start + end) / 2;
			
			ForkJoinCalculate left = new ForkJoinCalculate(start, middle);
			left.fork(); //拆分,并将该子任务压入线程队列
			
			ForkJoinCalculate right = new ForkJoinCalculate(middle+1, end);
			right.fork();
			
			return left.join() + right.join();
		}
		
	}

测试类:

@Test
	public void test1(){
		long start = System.currentTimeMillis();
		
		ForkJoinPool pool = new ForkJoinPool();
		ForkJoinTask<Long> task = new ForkJoinCalculate(0L, 10000000000L);
		
		long sum = pool.invoke(task);
		System.out.println(sum);
		
		long end = System.currentTimeMillis();
		
		System.out.println("耗费的时间为: " + (end - start)); //112-1953-1988-2654-2647-20663-113808
	}

Stream的并行流: parallel

@Test
	public void test3(){
		long start = System.currentTimeMillis();
		Long sum = LongStream.rangeClosed(0L, 10000000000L)//0-10000000000L的数
							 .parallel()
							 .sum();
		System.out.println(sum);
		long end = System.currentTimeMillis();
		System.out.println("耗费的时间为: " + (end - start)); //2061-2053-2086-18926
	}


总结:stream的终止操作简直了,有的时候你忘记了sql怎么写,不管是排序还是分组还是分组计数,还是列转行等操作,

java8都能实现,而且有的时候为了考虑sql的效率我们也不可能写很多东东,就像前几天的一个需求,一个对象下的关联基础信息要给进行大于5的判断,只取前5个。。。。limit是吧,可我的sql已经够长了,本身就是多重嵌套,这个对象表相关的东东太多了。。。。那就只可以在代码中了,如果是以前你怎么做?现在呢?当然这个案列也没有很恰当,具体好不好使用了就知道。

 类似资料: