java 8新特性 之 stream

pipeline (管道)的概念

一个数据操作的流程,例如 转换,聚合,统计 ,遍历 等一系列操作构成一个数据通道,通道中的数据流就会被管道转换,聚合,统计 ,遍历。

pipeline的组成部分

数据源 :数据集,可以是I/O流,数组或集合等

中间操作:转换,聚合,统计 ,遍历 等

终结操作:对数据的最后操作,例如forEach等,执行终结操作,表明管道中的数据离开管道

stream的概念

stream是一组元素的序列,并不像传统的集合那样只保存元素,它携带数据通过管道,是数据的载体。

例子:

roster的类型是List<Person>

roster
    .stream()//转换成流
    .filter(e -> e.getGender() == Person.Sex.MALE)//过滤  中间操作
    .forEach(e -> System.out.println(e.getName()));//遍历  终结操作

上面的一系列操作构成一个管道,如果仅仅是把数据源换了下面的操作不做更改,那么此 管道仍然可用。

一句话:管道相当于操作序列,流相当于数据载体,流通过管道会被管道的结构所影响

java.util.stream包

java.util.stream下的包提供了对元素流的函数式操作,例如对集合中的元素做转换,聚合,统计 ,遍历 等操作。

下面通过例子来学习关于流操作的用法,在这之前需要先定义一个Person类,用于数据的获取和之后的例子中

package com.stream;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.UUID;

public class Person {
	private int age;
	private String name;
	public Person(int age, String name) {
		super();
		this.age = age;
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public static List<Person> getListPerson(){
		List<Person> list=new ArrayList<>();
		for(int i=0;i<100;i++) {
			list.add(new Person(new Random().nextInt(30),UUID.randomUUID().toString().split("-")[0]));
		}
		return list;
	}
	@Override
	public String toString() {
		return "Person [age=" + age + ", name=" + name + "]";
	}
}

下面是具体的操作,包括过滤,转换,聚合,分组,多条件分组等操作:

package com.stream;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.model.*;

public class StreamTest {
	public static void main(String[] args) {
		List<Person> list=Person.getListPerson();
		
		System.out.println("过滤");
		List<Person> list1=list.stream().filter(p->p.getName().startsWith("a")).collect(Collectors.toList());
		System.out.println(list1);
		
		System.out.println("转换");
		List<String> list2=list.stream().map((p)->p.getName()).collect(Collectors.toList());
		System.out.println(list2);
		
		System.out.println("聚合 求和1");
		double sum=list.stream().mapToInt(p->p.getAge()).sum();
		System.out.println(sum);
		
		System.out.println("聚合 平均值1");
		double average=list.stream().mapToInt(p->p.getAge()).average().getAsDouble();
		System.out.println(average);
		
		System.out.println("聚合 求和2");
		double sum2=list.stream().map(p->p.getAge()).reduce(0, (a,b)->{return a+b;});
		System.out.println(sum2);
		
		
		System.out.println("聚合 平均值2");
		double average2=list.stream().map(Person::getAge).collect(Averager::new, Averager::accept, Averager::combine).average();
		System.out.println(average2);
		
		
		System.out.println("单条件分组");
		Map<Integer,List<Person>> groupByAge=list.stream().collect(Collectors.groupingBy(Person::getAge));
		for(Map.Entry<Integer, List<Person>> entry:groupByAge.entrySet()) {
			System.out.println(entry.getValue());
		}
		
		System.out.println("多条件分组");
		Map<Integer,Map<String,List<Person>>> groupByAgeAndNameStartWith=list.stream().collect(Collectors.groupingBy(Person::getAge,Collectors.groupingBy(p->p.getName().substring(0, 1))));
		for(Map.Entry<Integer,Map<String,List<Person>>> entryLevel1:groupByAgeAndNameStartWith.entrySet()) {
			Map<String,List<Person>>groupByAge1=entryLevel1.getValue();
			for(Map.Entry<String, List<Person>> entryLevel2:groupByAge1.entrySet()) {
				System.out.println(entryLevel1.getKey()+","+entryLevel2.getKey()+entryLevel2.getValue());
			}
		}
		
		
	}
}

其中的聚合求平均值用到了一个中间类Averager,用于提供中间操作的保存和迭代连接等操作,求平均值过程中会产生多个中间
Averager,最后调用连接方法将他们连接成一个Averager,该类代码如下:

package com.model;


 
import java.util.function.IntConsumer;

public class Averager implements IntConsumer
{
    private int total = 0;
    private int count = 0;
        
    public double average() {
        return count > 0 ? ((double) total)/count : 0;
    }
        
    public void accept(int i) { total += i; count++; }
    public void combine(Averager other) {
        total += other.total;
        count += other.count;
    }
}


 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值