Java8新特性之Stream流实战

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
  • 19
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wayfreem

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值