Java8新特性之Stream流实战

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_18948359/article/details/86527799

Stream 流的各种实战

学习了 Stream 之后,我们会遇到一个问题,就是如何使用Stream 流来进行我们的数据处理。

准备工作

创建一个 Employ 类

public class Employ{
	
	private String id;
	private String name;
	private int age;
	private String dept;
	private int gender;
	
	public Employ(){
	}
	
	public Employ(String id, String name, int age, String dept, int gender){
		this.id = id;
		this.name = name;
		this.age = age;
		this.dept = dept;
		this.gender = gender;
	}
	
	public void getInfo(){
		System.out.println("编码:"+this.id+",名称:"+ this.name +", 年龄:"+ this.age +", 部门:"+ this.dept + ",性别:" +this.gender);
	}
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getDept() {
		return dept;
	}
	public void setDept(String dept) {
		this.dept = dept;
	}
	public int getGender() {
		return gender;
	}
	public void setGender(int gender) {
		this.gender = gender;
	}
}

forEach()、limit()、skip() 方法

import java.util.*;

public class TestDemo {

	public static void main(String[] args) {

		List<Employ> employList = Arrays.asList(new Employ("0001", "张三", 30, "HR", 1),
				new Employ("0002", "李四", 15, "COO", 1), new Employ("0003", "王五", 26, "HR", 1),
				new Employ("0004", "赵六", 34, "COO", 1), new Employ("0005", "李刚", 55, "HR", 1),
				new Employ("0006", "李华", 23, "CTO", 1), new Employ("0007", "王麻子", 30, "HR", 1)	
		);
		
		// forEach 方法
		employList.stream().forEach(Employ :: getInfo);
		
		// limit 方法
		System.out.println("+++++++++++++++++++ limit方法 +++++++++++++++++++++");
		employList.stream().limit(3).forEach(Employ :: getInfo);
		
		// skip 与 limit 方法, 跳过第一个,然后向后取3个
		System.out.println("+++++++++++++++++++ skip 方法与 limit+++++++++++++++++++++");
		employList.stream().skip(1).limit(3).forEach(Employ :: getInfo);
		
	}
}

控制台输出

编码:0001,名称:张三, 年龄:30, 部门:HR,性别:1
编码:0002,名称:李四, 年龄:15, 部门:COO,性别:1
编码:0003,名称:王五, 年龄:26, 部门:HR,性别:1
编码:0004,名称:赵六, 年龄:34, 部门:COO,性别:1
编码:0005,名称:李刚, 年龄:55, 部门:HR,性别:1
编码:0006,名称:李华, 年龄:23, 部门:CTO,性别:1
编码:0007,名称:王麻子, 年龄:30, 部门:HR,性别:1
+++++++++++++++++++ limit方法 +++++++++++++++++++++
编码:0001,名称:张三, 年龄:30, 部门:HR,性别:1
编码:0002,名称:李四, 年龄:15, 部门:COO,性别:1
编码:0003,名称:王五, 年龄:26, 部门:HR,性别:1
+++++++++++++++++++ skip 方法与 limit+++++++++++++++++++++
编码:0002,名称:李四, 年龄:15, 部门:COO,性别:1
编码:0003,名称:王五, 年龄:26, 部门:HR,性别:1
编码:0004,名称:赵六, 年龄:34, 部门:COO,性别:1

distinct()、 Collectors.toSet()、Collectors.toList() 方法

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class TestDemo {

	public static void main(String[] args) {

		List<Employ> employList = Arrays.asList(new Employ("0001", "张三", 30, "HR", 1),
				new Employ("0002", "李四", 15, "COO", 1), new Employ("0003", "王五", 26, "HR", 1),
				new Employ("0004", "赵六", 34, "COO", 1), new Employ("0005", "李刚", 55, "HR", 1),
				new Employ("0006", "李华", 23, "CTO", 1), new Employ("0007", "王麻子", 30, "HR", 1));

		// 使用 distinct 来去重
		Stream<String> stream = employList.stream().map(Employ::getDept).distinct();
		List<String> nameList = stream.collect(Collectors.toList()); // 将数据转为list
		nameList.forEach(System.out::println);
		System.out.println( "==========================" );
		
		// 使用 Collectors.toSet() 无序+去重
		Stream<String> stream1 = employList.stream().map(Employ::getDept).distinct();
		Set<String> nameList1 = stream1.collect(Collectors.toSet());
		nameList1.forEach(System.out::println);
		System.out.println( "==========================" );
		
		// 使用 Collectors.toList() 转换为 list
		Stream<String> stream2=  employList.stream().map(i->i.getName());
        List<String> nameList2= stream2.collect(Collectors.toList());
        nameList2.forEach(System.out::println);
	}
}

sorted() 排序,以及 reversed() 倒置

import java.util.*;

public class TestDemo {
	
	public static void main(String[] args) {
        // 创建数据
		List<Employ> employList = Arrays.asList(new Employ("0001", "张三", 30, "HR", 1),
				new Employ("0002", "李四", 15, "COO", 1), new Employ("0003", "王五", 26, "HR", 1),
				new Employ("0004", "赵六", 34, "COO", 1), new Employ("0005", "李刚", 55, "HR", 1),
				new Employ("0006", "李华", 23, "CTO", 1), new Employ("0007", "王麻子", 30, "HR", 1)	
		);
		
		// sorted 方法排序
		employList.stream().sorted(Comparator.comparing( employ -> employ.getAge())).forEach(Employ :: getInfo);
		
		System.out.println("=====================================================");
		
		// reversed 方法倒置排序
		employList.stream().sorted(Comparator.comparing(Employ:: getAge).reversed()).forEach(Employ :: getInfo);
	}
}

控制台输出

编码:0002,名称:李四, 年龄:15, 部门:COO,性别:1
编码:0006,名称:李华, 年龄:23, 部门:CTO,性别:1
编码:0003,名称:王五, 年龄:26, 部门:HR,性别:1
编码:0001,名称:张三, 年龄:30, 部门:HR,性别:1
编码:0007,名称:王麻子, 年龄:30, 部门:HR,性别:1
编码:0004,名称:赵六, 年龄:34, 部门:COO,性别:1
编码:0005,名称:李刚, 年龄:55, 部门:HR,性别:1
=====================================================
编码:0005,名称:李刚, 年龄:55, 部门:HR,性别:1
编码:0004,名称:赵六, 年龄:34, 部门:COO,性别:1
编码:0001,名称:张三, 年龄:30, 部门:HR,性别:1
编码:0007,名称:王麻子, 年龄:30, 部门:HR,性别:1
编码:0003,名称:王五, 年龄:26, 部门:HR,性别:1
编码:0006,名称:李华, 年龄:23, 部门:CTO,性别:1
编码:0002,名称:李四, 年龄:15, 部门:COO,性别:1

map() 方法与 max()、min()、count() 的用法

import java.util.*;
import java.util.stream.Stream;

public class TestDemo {

	public static void main(String[] args) {

		List<Employ> employList = Arrays.asList(new Employ("0001", "张三", 30, "HR", 1),
				new Employ("0002", "李四", 15, "COO", 1), new Employ("0003", "王五", 26, "HR", 1),
				new Employ("0004", "赵六", 34, "COO", 1), new Employ("0005", "李刚", 55, "HR", 1),
				new Employ("0006", "李华", 23, "CTO", 1), new Employ("0007", "王麻子", 30, "HR", 1));

		// 使用 map 方法以及 max 方法获取年龄最大的对象年龄
		Optional<Integer> opAgeMax = employList.stream().map(Employ::getAge).max((x, y) -> x.compareTo(y));
		if (opAgeMax.isPresent()) {
			System.out.println("max:" + opAgeMax.get()); // max:55
		} else {
			System.out.println("max:没找到");
		}

		// 使用 min 方法获取 年龄最小的对象年龄
		Optional<Integer> opAgeMin = employList.stream().map(Employ::getAge).min((x, y) -> x.compareTo(y));
		if (opAgeMin.isPresent()) {
			System.out.println("min:" + opAgeMin.get()); // min:15
		} else {
			System.out.println("min:没找到");
		}

		// count 方法
		long count = employList.stream().count(); // 计算有几个值,和 employList.size() 一样
		System.out.println(count); // 7
		System.out.println("==================");

		// 将数据按照年龄排序
		Stream<Integer> stream = employList.stream().map(employ -> employ.getAge()).sorted();
		stream.forEach(i -> System.out.println(i));
	}
}

控制台输出

max:55
min:15
7
===========================
15
23
26
30
30
34
55

DoubleSummaryStatistics 对数据的操作

import java.util.*;
import java.util.stream.Collectors;

public class TestDemo {

	public static void main(String[] args) {

		List<Employ> employList = Arrays.asList(new Employ("0001", "张三", 30, "HR", 1),
				new Employ("0002", "李四", 15, "COO", 1), new Employ("0003", "王五", 26, "HR", 1),
				new Employ("0004", "赵六", 34, "COO", 1), new Employ("0005", "李刚", 55, "HR", 1),
				new Employ("0006", "李华", 23, "CTO", 1), new Employ("0007", "王麻子", 30, "HR", 1));

		
		DoubleSummaryStatistics dss= employList.stream().collect(Collectors.summarizingDouble(Employ::getAge));
		System.out.println("max:"+dss.getMax());		// max:55.0
        System.out.println("min:"+dss.getMin());		// min:15.0
        System.out.println("sum:"+dss.getSum());		// sum:213.0
        System.out.println("average:"+dss.getAverage());	// average:30.428571428571427
        System.out.println("count:"+dss.getCount());		// count:7
	}
}

使用 reduce() 方法

下面代码例如第一个示例的 reduce(),第一个参数(空白字符)即为起始值,第二个参数(String::concat)为 BinaryOperator。这类有起始值的 reduce() 都返回具体的对象。而对于第四个示例没有起始值的 reduce(),由于可能没有足够的元素,返回的是 Optional,请留意这个区别。

import java.util.stream.Stream;

public class Reduce {

	public static void main(String[] args) {

		// 连接字符串
		String concat = Stream.of("A", "B", "C", "D").reduce("", String::concat);
		System.out.println(concat); // ABCD

		// 过滤,字符串连接
		concat = Stream.of("a", "B", "c", "D", "e", "F").filter(x -> x.compareTo("Z") > 0).reduce("", String::concat);
		System.out.println(concat);

		// 求最小值
		double minValue = Stream.of(-1.5, 1.0, -3.0, -2.0).reduce(Double.MAX_VALUE, Double::min);
		System.out.println(minValue); // -3.0

		// 求和, 有起始值
		int sumValue = Stream.of(1, 2, 3, 4).reduce(0, Integer::sum);
		System.out.println(sumValue); // 10

		// 求和, 无起始值
		sumValue = Stream.of(1, 2, 3, 4).reduce(Integer::sum).get();
		System.out.println(sumValue); // 10
	}
}

groupingBy 分组

import java.util.*;
import java.util.stream.Collectors;

public class TestDemo {

	public static void main(String[] args) {

		List<Employ> employList = Arrays.asList(new Employ("0001", "张三", 30, "HR", 1),
				new Employ("0002", "李四", 15, "COO", 1), new Employ("0003", "王五", 26, "HR", 1),
				new Employ("0004", "赵六", 34, "COO", 1), new Employ("0005", "李刚", 55, "HR", 1),
				new Employ("0006", "李华", 23, "CTO", 1), new Employ("0007", "王麻子", 30, "HR", 1));

		// 使用分组
		Map<String, List<Employ>> map = employList.stream().collect(Collectors.groupingBy(Employ::getDept));
		System.out.println(map);
		
		

		// 进一步对数据进行处理
		map.keySet().forEach( key -> {
			String name = map.get(key).stream().map( Employ::getName ).reduce("|名称:", (x,y) -> {return x+","+y;});
			System.out.println("key:"+key+"|count:"+ map.get(key).size() +name);
		});
	}
}

控制台输出

{COO=[Employ@214c265e, Employ@448139f0],HR=[Employ@7cca494b, Employ@7ba4f24f, Employ@3b9a45b3, Employ@7699a589],CTO=[Employ@58372a00]}
key:COO|count:2|名称:,李四,赵六
key:HR|count:4|名称:,张三,王五,李刚,王麻子
key:CTO|count:1|名称:,李华

anyMatch()、findAny()、findFirst() 方法

findAny、findFirst 的返回值都是 Optional 类型,避免了 Stream 序列为空时返回 null。

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class TestDemo {

	public static void main(String[] args) {

		List<Employ> employList = Arrays.asList(new Employ("0001", "张三", 30, "HR", 1),
				new Employ("0002", "李四", 15, "COO", 1), new Employ("0003", "王五", 26, "HR", 1),
				new Employ("0004", "赵六", 34, "COO", 1), new Employ("0005", "李刚", 55, "HR", 1),
				new Employ("0006", "李华", 23, "CTO", 1), new Employ("0007", "王麻子", 30, "HR", 1));

		// 使用 anyMatch 来查找
		boolean bEixst = employList.stream().anyMatch(i -> i.getName().equals("李四"));
		System.out.println(bEixst);		// true
		
		// 用来查找任意一个对象
		Optional<Employ> opWorker=  employList.stream().findAny();
        if(opWorker.isPresent()){
            System.out.println(opWorker.get());	// Employ@4eec7777
            opWorker.get().getInfo();			// 编码:0001,名称:张三, 年龄:30, 部门:HR,性别:1
        }
        else {
            System.out.println("没找到");
        }
        System.out.println("==========================");
        
        // 使用 filter 过滤数据
        Stream<Employ> streamEmploy = employList.stream().filter( employ -> employ.getDept().equals("HR"));
        List<Employ> filterEmployList = streamEmploy.collect(Collectors.toList());
        filterEmployList.forEach( Employ :: getInfo );
        
        System.out.println("==========================");
        Optional<Employ> opEmploy = employList.stream().filter( employ -> employ.getDept().equals("HR")).findFirst();
        System.out.println(opWorker.get());
	}
}

控制台输出:

true
Employ@4eec7777
编码:0001,名称:张三, 年龄:30, 部门:HR,性别:1
==========================
编码:0001,名称:张三, 年龄:30, 部门:HR,性别:1
编码:0003,名称:王五, 年龄:26, 部门:HR,性别:1
编码:0005,名称:李刚, 年龄:55, 部门:HR,性别:1
编码:0007,名称:王麻子, 年龄:30, 部门:HR,性别:1
==========================
Employ@4eec7777

猜你喜欢

转载自blog.csdn.net/qq_18948359/article/details/86527799