StreamAPI的使用

 

 

1.    Stream 关注的是对数据的运算,与CPU打交道
    集合关注的是数据存储,与内存打交道

 2.特点

 (1) 自己不会存储元素
 (2) 不会改变源对象。相反,他们会返回一个持有结果的新的Stream
(3) 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行

3. Stream执行流程 

 (1) Stream实例化
(2) 一系列的中间操作(过滤、映射...)
 (3) 终止操作

 4. 说明

 (1) 一个中间操作链,对数据源的数据进行处理
 (2) 一旦执行终止操作,就执行中间操作链,共产生结果。之后,不会再被使用

数据准备 

Employee类 

public class Employee {

	private int id;
	private String name;
	private int age;
	private double salary;
	
	public Employee(int id, String name, int age, double salary) {
		
		this.id = id;
		this.name = name;
		this.age = age;
		this.salary = salary;
	}
	
	public Employee() {
		
	}

	public int getId() {
		return id;
	}

	public void setId(int 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 double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}

	@Override
	public String toString() {
		return "Employee [id=" + id + ", name=" + name + ", age=" + age + ", salary=" + salary + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + id;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		long temp;
		temp = Double.doubleToLongBits(salary);
		result = prime * result + (int) (temp ^ (temp >>> 32));
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Employee other = (Employee) obj;
		if (age != other.age)
			return false;
		if (id != other.id)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		if (Double.doubleToLongBits(salary) != Double.doubleToLongBits(other.salary))
			return false;
		return true;
	}
	
	
	
}

 EmployeeData

import java.util.ArrayList;
import java.util.List;

public class EmployeeData {

	public static List<Employee> getEmployee(){
		List<Employee> list=new ArrayList<>();
		
		list.add(new Employee(1001,"马化腾",34,6000.38));
		list.add(new Employee(1002,"马云",12,9876.12));
		list.add(new Employee(1003,"刘强东",34,3000.82));
		list.add(new Employee(1004,"雷军",26,7657.37));
		list.add(new Employee(1005,"李彦宏",65,5555.32));
		list.add(new Employee(1006,"比尔盖茨",42,9500.43));
		list.add(new Employee(1007,"任正非",26,4333.32));
		list.add(new Employee(1008,"扎克伯格",35,2500.32));
		
		return list;
	}
}

Stream的实例化方法

public class StreamAPITest {

	/**
	 * 测试Stream的实例化
	 */
	// 创建Stream 方式一: 通过集合
	public void test1() {
		List<Employee> employees= EmployeeData.getEmployee();
		
		// default Stream<E> stream() : 返回一个顺序流
		Stream<Employee> stream = employees.stream();
		
		// default Stream<E> parallelStream(): 返回一个并行流
		Stream<Employee> parallelStream = employees.parallelStream();
	}
	
	//创建 Stream 方式二: 通过数组
	@Test
	public void test2() {
		int [] arr = {1,2,3,4,5,6};
		//调用Arrays类的static<T> Stream<T> stream (T [] array) :返回一个流
		IntStream stream = Arrays.stream(arr);
		
		Employee e1 = new Employee(100,"Tom", 0, 0);
		Employee e2 = new Employee(100,"Tom", 0, 0);
		
		Employee [] arr2 = {e1,e2};
		Stream<Employee> stream2= Arrays.stream(arr2);
	}
	
	//创建Stream方式三:通过Stream的of()
	@Test
	public void test3() {
		Stream<Integer> stream=Stream.of(1,2,3,4,5,6);
	}
	
	//创建Stream方式四: 创建无限流
	@Test
	public void test4() {
		//遍历前10个偶数
		Stream.iterate(0, t->t+2).limit(10).forEach(System.out::println);
		System.out.println("------------------");
		
		//打印10个随机小数
		Stream.generate(Math::random).limit(10).forEach(i->System.out.println(i));
	}
}

Stream的中间操作

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

import org.junit.jupiter.api.Test;

public class StreamAPITest2 {

	/**
	 * 测试Stream的中间操作
	 */
	// 1. 筛选和切片
	@Test
	public void test1() {
		List<Employee> list=EmployeeData.getEmployee();
		
		System.out.println("---------filter------");
		// filter(Predicate p) ----接收 Lambda,从流中排除某些元素
		Stream<Employee> stream=list.stream();
		// 练习:查询员工表中,员工工资大于7000的员工信息
		stream.filter(e -> e.getSalary()>7000).forEach(i->System.out.println(i));
		
		System.out.println("------limit(n)--------");
		
		//limit(n) 截断流 ,使其元素不超过给定数量
		list.stream().limit(3).forEach(System.out::println);
		
		System.out.println("----skip(n)------");
		
		// skip(n) --跳过元素,返回一个扔掉了前n个元素的流
		list.stream().skip(3).forEach(i->System.out.println(i));
		
		//distinct() --筛选,通过流所生成元素的hasnCode()和equals() 去除重复元素
		System.out.println("-------------------distinct-------------");
		list.add(new Employee(1010,"刘强东",40,8000));
		list.add(new Employee(1010,"刘强东",40,8000));
		list.add(new Employee(1010,"刘强东",40,8000));
		list.add(new Employee(1010,"刘强东",40,8000));
		list.add(new Employee(1010,"刘强东",40,8000));
		list.add(new Employee(1010,"刘强东",40,8000));
		
		list.stream().distinct().forEach(i->System.out.println(i));
	}
	
	//映射
	@Test
	public void test2() {
		//map (function f) --接收一个函数作为参数,将元素转换为其他形式或提取信息
		List<String> list = Arrays.asList("aa","bb","cc","dd");
		list.stream().map(str -> str.toUpperCase()).forEach(System.out::println);
		
		//练习:获取员工姓名长度大于3的员工姓名
		System.out.println("---------nameStreamFilter----------");
		List<Employee> employees = EmployeeData.getEmployee();
		Stream<String> nameStream = employees.stream().map(e -> e.getName());
		nameStream.filter(name -> name.length()>3).forEach(System.out::println);;
		
		System.out.println("------------");
		//flatMap(Function f) -- 接收一个函数作为参数,将流中的每个值换位另一个流,然后把所有的流连成一个流
		Stream<Character> charStream = list.stream().flatMap(StreamAPITest2::fromStringToStream);
		charStream.forEach(System.out::println);
	}
	
	//将字符串中的多个字符串构成的集合转换为对应的Stream实例
	public static Stream<Character> fromStringToStream(String str){
		ArrayList<Character> list= new ArrayList<>();
		for(Character c:str.toCharArray()) {
			list.add(c);
		}
		return list.stream();
	}
	
	//3--排序
	@Test
	public void test4() {
		//sorted--自然排序
		System.out.println("----sorted--------");
		List<Integer> list = Arrays.asList(12,43,65,34,87,0,-98,7);
		list.stream().sorted().forEach(System.out::println);
		
		//sorted(Compare com) -- 定制排序
		System.out.println("------sorted(com)-----");
		List<Employee> employees = EmployeeData.getEmployee();
		employees.stream().sorted( (e1,e2)->{
			return (e1.getAge()-e2.getAge());
		} ).forEach(System.out::println);
	}
	
}

测试终止植操作

 1. 匹配和查找

import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;

import org.junit.jupiter.api.Test;

/**
 * 测试终止操作
 * @author CharlieLiang
 *
 */
public class StreamAPITest3 {

	//1-- 匹配与查找
	@Test
	public void test1() {
		List<Employee> employees = EmployeeData.getEmployee();
		//allMath(Predicate p) -- 检查是否匹配所有元素
		// 练习:是否所有员工的年龄都大于18
		System.out.println("-------allMath----------");
		boolean allMath= employees.stream().allMatch( e -> e.getAge()>10);
		System.out.println(allMath);
		
		System.out.println("--------anyMatch----------");
		//anyMatch(Predicate p) -- 检查是否至少匹配一个袁术
		//练习:是否存在员工工资大于10000
		boolean anyMatch = employees.stream().anyMatch( e -> e.getSalary()>1000);
		System.out.println(anyMatch);
		
		System.out.println("----noneMath-------");
		//练习: 是否不存在员工姓雷
		boolean noneMath = employees.stream().noneMatch( e -> e.getName().startsWith("雷"));
		System.out.println(noneMath);
		
		System.out.println("------findFirst------");
		Optional<Employee> firstEmployee = employees.stream().findFirst();
		System.out.println(firstEmployee);
		
		System.out.println("--------findAny-----------");
		Optional<Employee> findAny = employees.parallelStream().findAny();
		System.out.println(findAny);
	}
	
	
	@Test
	public void test2() {
		List<Employee> employees = EmployeeData.getEmployee();
		// count -- 返回流中元素的总个数
		System.out.println("---------count-----------");
		long count = employees.stream().filter( e -> e.getSalary()>5000).count();
		System.out.println(count);
		
		// 练习返回最高工资
		System.out.println("--------max--------");
		Stream<Double> salaryStream = employees.stream().map( e -> e.getSalary());
		Optional<Double> maxSalary = salaryStream.max(
			(s1,s2) -> {
				return (int) (s1-s2);
			}
		);
		System.out.println(maxSalary);
		
		System.out.println("--------max2------");
		Stream<Double> salaryStream2 = employees.stream().map( e -> e.getSalary());
		Optional<Double> maxSalary2 = salaryStream2.max(Double::compare);
		System.out.println(maxSalary2);
		
		// 返回最低工资的员工
		System.out.println("---min---");
		Optional<Employee> minSalaryEmployee = 
				employees.stream().min( (e1,e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
		System.out.println(minSalaryEmployee);
		
		//forEach (Consumer c) --- 内部迭代
		employees.stream().forEach(i -> System.out.println(i));
		
		// 或者
		// employees.forEach(System.out::println);
	}
}

2. 归约测试

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;

import org.junit.jupiter.api.Test;
/**
 * 归约测试
 * @author CharlieLiang
 *
 */
public class StreamAPITest4 {

	
	@Test
	public void test1() {
		//reduce (T identity, BinaryOperator) -- 可以将流中的元素反复结合起来,得到一个值。返回T
		// 练习计算1-10的自然数的和
		System.out.println("----reduce-----");
		List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
		// 0: 表示初始值是0
		Integer sum = list.stream().reduce(0 , Integer::sum);
		System.out.println(sum);
		
		System.out.println("---reduce2----");
		
		List<Integer> list2 = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
		// 0: 表示初始值是0
		Integer sum2 = list2.stream().reduce(0 , (a,b) -> (a+b));
		System.out.println(sum2);
		
		
		System.out.println("-----reduce(Optional T)---");
		// reduce(BinaryOperator b)--可以将流中元素反复结合起来,得到一个值。返回 Optional<T>
		List<Employee> employees = EmployeeData.getEmployee();
		Stream<Double> salaryStream = employees.stream().map(Employee::getSalary);
		Optional<Double> salarySum = salaryStream.reduce(Double::sum);
		System.out.println(salarySum);
		
		System.out.println("-----reduce(Optional T)2---");
		Stream<Double> salaryStream2 = employees.stream().map(Employee::getSalary);
		Optional<Double> salarySum2 = salaryStream2.reduce((a,b) -> (a+b) );
		System.out.println(salarySum2);
	}
}

3. 收集测试

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.junit.jupiter.api.Test;

/**
 * 收集测试
 * @author CharlieLiang
 *
 */
public class StreamAPITest5 {

	@Test
	public void test1() {
		// collect(Collector c) -- 将流转化为其他形式。接收一个Collector接口的实现,
		// 用于给Stream中元素做汇总的方法
		//练习:查找工资大于6000的员工,结果返回一个List或Set
		System.out.println("---toList----");
		List<Employee> employees = EmployeeData.getEmployee();
		List<Employee> empList = employees.stream().filter( e -> e.getSalary()>6000).collect(Collectors.toList());
		empList.forEach(System.out::println);
		
		System.out.println("---toSet----");
		Set<Employee> empSet = employees.stream().filter( e -> e.getSalary()>6000).collect(Collectors.toSet());
		empSet.forEach( i -> System.out.println(i));
	}
}

Optional类的使用

介绍

 Optional类: 为了在程序中避免出现空指针异常而创建的
常用的方法 :  ofNullable(T t)
                       ofElse(T t) 

数据准备

girl类 

public class Girl {

	private String name;

	public Girl(String name) {

		this.name = name;
	}

	public Girl() {

	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Girl [name=" + name + "]";
	}
	
}

 Boy类

public class Boy {

	private Girl girl;

	public Boy(Girl girl) {
		this.girl = girl;
	}

	public Boy() {
		
	}

	public Girl getGirl() {
		return girl;
	}

	public void setGirl(Girl girl) {
		this.girl = girl;
	}

	@Override
	public String toString() {
		return "Boy [girl=" + girl + "]";
	}
	
}

测试类 

import java.util.Optional;

import org.junit.jupiter.api.Test;

/**
 * Optional类: 为了在程序中避免出现空指针异常而创建的
 * 常用的方法 : ofNullable(T t)
 * 			    ofElse(T t)
 * @author CharlieLiang
 *
 */
public class OptionTest {

	/**
	 * Option.of(T t): 创建一个Optional实例,t必须非空
	 * Optional.empty(): 创建一个空的Optional实例
	 * Optional.ofNullable(T t): t可以为null
	 */
	
	@Test
	public void test1() {
		Girl girl = new Girl();
		Optional<Girl> optionalGirl = Optional.of(girl);
		System.out.println(optionalGirl);
	}
//	----------------------------
	@Test
	public void test2() {
		Girl girl = new Girl();
		Optional<Girl> optionalGirl = Optional.ofNullable(girl);
		System.out.println(optionalGirl);
		
		System.out.println("---------");
		
		Girl girl2 = null;
		Optional<Girl> optionalGirl2 = Optional.ofNullable(girl2);
		System.out.println(optionalGirl2);
		
		System.out.println("--------");
		
		//orElse(T t1) : 如果当前的Optional内部封装的t是非空的,则返回内部的t
		// 如果内部的t是空的,则返回orElse() 方法中的参数t1
		Girl girl3 = optionalGirl2.orElse( new Girl("小梅"));
		System.out.println(girl3);
	}
//	-----------------------------------
	public String getGirlName(Boy boy) {
		return boy.getGirl().getName();
	}
	
	@Test
	public void test3() {
		Boy boy = new Boy();
		String girlName = getGirlName(boy);
		System.out.println(girlName);
	}
//	----------------------------------
	
	
	// 优化以后的版本
	public String getGirlName2(Boy boy) {
		if(boy != null ) {
			Girl girl=boy.getGirl();
			if(girl != null) return girl.getName();
		}
		return null;
	}
	
	@Test
	public void test4() {
		Boy boy = new Boy();
		String girlName = getGirlName2(boy);
		System.out.println(girlName);
	}
//	------------------------------------
	
	// 使用Optinal类getGirlName():
	public String getGirlName3(Boy boy) {
		Optional<Boy> boyOptional = Optional.ofNullable(boy);
		// 此时boy2一定非空
		Boy boy2 = boyOptional.orElse(new Boy(new Girl("大梅")));
		
		Girl girl=boy2.getGirl();
		Optional<Girl> girlOptional = Optional.ofNullable(girl);
		// girl2 一定非空
		Girl girl2 = girlOptional.orElse(new Girl("小娟"));
		
		return girl2.getName();
	}
	
	@Test
	public void test5() {
		Boy boy = null;
		String girlName = getGirlName3(boy);
		System.out.println(girlName);
		
		System.out.println("---------");
		
		Boy boy2 = new Boy();
		String str= getGirlName3(boy2);
		System.out.println(str);
		
		System.out.println("----------");
		
		Boy boy3 = new Boy( new Girl("陈老师") );
		String strChen= getGirlName3(boy3);
		System.out.println(strChen);
	}
	
}

运行结果:

test1

 test2

 test3

NullPointerException

test4

 test5

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值