Java Stream API

1.什么是Stream API?

Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。

 

2.Stream操作的三个步骤

2.1创建Stream

创建包含四种方式,但是创建出来的仅仅是流而已并不能存储元素、改变源对象,并且它的操作是延迟执行的。(只有在需要结果的时候才执行)

import org.junit.Test;

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

public class Stream1 {
    // 创建Stream
    @Test
    public void test1() {
        //1.可以通过Collection系列集合提供的stream()(获取串行流)或parallelStream()(获取并行流)
        List<String> list = new ArrayList<>();
        Stream<String> s1 = list.stream();

        // 2.通过Arrays的静态方法stream()可以获取数组流
        Employee[] emps = new Employee[10];
        Stream<Employee> s2 = Arrays.stream(emps);

        //3.可以使用静态方法Stream.of(),通过显示值创建一个流
        Stream<String> s3 = Stream.of("aa", "bb", "cc");

        //4.可以使用静态方法 Stream.iterate() 和 Stream.generate(), 创建无限流
        //迭代 按照一元运算的规律产生一个无限流
        Stream<Integer> s4 = Stream.iterate(0, (x) -> x + 2);
        s4.limit(10).forEach(System.out::println);
        //生成
        Stream<Integer> s5 = Stream.generate(() -> (int) (Math.random()*100));
        s5.limit(10).forEach(System.out::println);

    }
}

2.2中间操作

多个中间操作可以连接起来形成一个流水线,除非流水 线上触发终止操作,否则中间操作不会执行任何的处理! 而在终止操作时一次性全部处理,称为“惰性求值”。

2.2.1筛选与切片

方法描述
filter(Predicate p)接收 Lambda , 从流中排除某些元素。
distinct()筛选,通过流所生成元素的 hashCode() 和 equals() 去 除重复元素
limit(long maxSize)截断流,使其元素不超过给定数量
skip(long n)跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素 不足 n 个,则返回一个空流。与 limit(n) 互补
import org.junit.Test;

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

public class Stream2 {
    List<Employee> employees = Arrays.asList(
            new Employee("张三", 18, 1111.33),
            new Employee("李四", 19, 2222.44),
            new Employee("王五", 20, 3333.55),
            new Employee("赵六", 21, 4444.66),
            new Employee("田七", 22, 5555.77),
            new Employee("田七", 22, 5555.77)
    );
    @Test
    public void test1(){
        //过滤
        Stream<Employee> s1=employees.stream()
                .filter((e)->{
                    //中间操作不会执行任何操作
                    System.out.println("惰性求值");
                    return e.getAge()>20;});
                //当有终止操作时才会一次性执行
        //内部迭代 - 迭代操作由Stream API 完成操作
        s1.forEach(System.out::println);

        //外部迭代 通过迭代器循环
        Iterator<Employee> iterator = employees.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
    @Test
    public void test2(){
        //截断流
        employees.stream().limit(2).forEach(System.out::println);
    }

    @Test
    public void test3(){
        //跳过
        employees.stream()
                .filter((e)->e.getAge()>20)
                .skip(1)
                .forEach(System.out::println);
    }

    @Test
    public void test4(){
        //筛选去重
        employees.stream()
                .filter((e)->e.getAge()>20)
                .distinct()
                .forEach(System.out::println);
    }
}

2.2.2映射

方法描述
map(Function f)接收一个函数作为参数,该函数会被应用到每个元 素上,并将其映射成一个新的元素。
mapToDouble(ToDoubleFunction f)接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的 DoubleStream。
mapToInt(ToIntFunction f)接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的 IntStream。
mapToLong(ToLongFunction f)接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的 LongStream。
flatMap(Function f)接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
import org.junit.Test;

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

public class Stream3 {
    List<Employee> employees = Arrays.asList(
            new Employee("张三", 18, 1111.33),
            new Employee("李四", 19, 2222.44),
            new Employee("王五", 20, 3333.55),
            new Employee("赵六", 21, 4444.66),
            new Employee("田七", 22, 5555.77),
            new Employee("田七", 22, 5555.77)
    );
    @Test
    public void test1 (){
        List<String> list1= Arrays.asList("aaa","bbb","ccc");
        list1.stream()
                .map((s)->s.toUpperCase())
                .forEach(System.out::println);

        employees.stream()
                .map(Employee::getAge)
                .forEach(System.out::println);
    }

    //写一个方法,解析字符串,将字符串中的字符一个个放到集合中
    public static Stream<Character> filterCharacter(String str){
        List<Character> list = new ArrayList<>();

        // 字符串转换成字符数组,把一个个字符提取出来
        for(Character ch:str.toCharArray()){
            list.add(ch);
        }

        return list.stream();
    }

    @Test
    public void test2(){
        List<String> list1= Arrays.asList("aaa","bbb","ccc");
        Stream<Stream<Character>> s1=list1.stream().map(Stream3::filterCharacter);
        s1.forEach((sm)->{
            sm.forEach(System.out::println);
        });

        list1.stream()
                .flatMap(Stream3::filterCharacter)
                .forEach(System.out::println);
    }
}

2.2.3排序

方法描述
sorted()产生一个新流,其中按自然顺序排序
sorted(Comparator comp)产生一个新流,其中按比较器顺序排序
import org.junit.Test;

import java.util.Arrays;
import java.util.List;

public class Stream4 {
    List<Employee> employees = Arrays.asList(
            new Employee("张三", 18, 1111.33),
            new Employee("李四", 19, 2222.44),
            new Employee("王五", 20, 3333.55),
            new Employee("赵六", 21, 4444.66),
            new Employee("田七", 22, 5555.77),
            new Employee("田七", 22, 5555.77)
    );
    @Test
    public void test1 (){
        employees.stream()
                .sorted((e1,e2)->{
                    if(e1.getAge().equals(e2.getAge())){
                        return e1.getName().compareTo(e2.getName());
                    }else {
                        return e1.getAge().compareTo(e2.getAge());
                    }
                })
                .forEach(System.out::println);
    }
}

2.3终止操作

2.3.1查找与匹配

方法描述
allMatch(Predicate p)检查是否匹配所有元素
anyMatch(Predicate p)检查是否至少匹配一个元素
noneMatch(Predicate p)检查是否没有匹配所有元素
findFirst()返回第一个元素
findAny()返回当前流中的任意元素
count()返回流中元素总数
max(Comparator c)返回流中最大值
min(Comparator c)返回流中最小值
import lombok.Data;


@Data
public class Employee {
    private String name;
    private Integer age;
    private double salary;
    private Status status;

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

    public Employee(String name, int age, double salary, Status status) {
        super();
        this.name = name;
        this.age = age;
        this.salary = salary;
        this.status = status;
    }

    public Employee() {
        this.name = null;
        this.age = 0;
        this.salary = 0;
    }

    public Employee(int age) {
        this.name = null;
        this.age = age;
        this.salary = 0;
    }

    public enum Status {
        FREE, BUSY, VOCATION;
    }
}
import org.junit.Test;

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

public class Stream5 {
    List<Employee> employees = Arrays.asList(
            new Employee("张三", 18, 1111.33, Employee.Status.BUSY),
            new Employee("李四", 19, 2222.44, Employee.Status.FREE),
            new Employee("王五", 20, 3333.55, Employee.Status.VOCATION),
            new Employee("赵六", 21, 4444.66, Employee.Status.BUSY),
            new Employee("田七", 22, 5555.77, Employee.Status.FREE)
    );

    @Test
    public void test1() {
        //检查是否匹配所有元素
        boolean b1 = employees.stream().allMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b1);
        //检查是否至少匹配一个元素
        boolean b2 = employees.stream().anyMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b2);
        //检查是否没有匹配所有元素
        boolean b3 = employees.stream().noneMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b3);

        //返回第一个元素
        //optional 返回的值有可能为空就封装到这个容器中
        Optional<Employee> emp = employees.stream()
                .sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))
                .findFirst();
        System.out.println(emp.get());

        //返回当前流中的任意元素
        Optional<Employee> emp1=employees.parallelStream().filter((e)->e.getStatus().equals(Employee.Status.FREE)).findAny();
        System.out.println(emp1.get());
    }
    @Test
    public void test2(){
        //返回流中元素的总个数
       Long l1= employees.stream().count();
        System.out.println(l1);

        //返回流中最大值
        Optional<Employee> op1=employees.stream()
                .max((e1,e2)->Double.compare(e1.getSalary(),e2.getSalary()));
        System.out.println(op1.get());
        //返回流中最小值
        Optional<Double> op2=employees.stream()
                .map(Employee::getSalary)
                .min(Double::compare);
        System.out.println(op2.get());
    }
}

2.3.2规约

方法描述
reduce(T iden, BinaryOperator b)可以将流中元素反复结合起来,得到一个值。 返回 T
reduce(BinaryOperator b)可以将流中元素反复结合起来,得到一个值。 返回 Optional< T>

2.3.3收集

import org.junit.Test;

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

public class Stream6 {
    List<Employee> employees = Arrays.asList(
            new Employee("张三", 18, 1111.33, Employee.Status.BUSY),
            new Employee("李四", 19, 2222.44, Employee.Status.FREE),
            new Employee("王五", 20, 3333.55, Employee.Status.VOCATION),
            new Employee("赵六", 21, 4444.66, Employee.Status.BUSY),
            new Employee("田七", 22, 5555.77, Employee.Status.FREE),
            new Employee("田七", 22, 5555.77, Employee.Status.FREE)
    );

    @Test
    public void test1() {
        //reduce 可以将流中元素反复结合起来,得到一个值
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        Integer sum = list.stream()
                .reduce(0, (x, y) -> x + y);
        System.out.println(sum);

        //有可能为空的值就封装到Optional
        Optional<Double> op1 = employees.stream()
                .map(Employee::getSalary)
                .reduce(Double::sum);
        System.out.println(op1.get());
    }

    @Test
    public void test2() {
        //collection 将流转换为其他形式,接收一个collector接口的实现,用于给stream中元素做汇总的方法
        //将当前员工的名字提取出来,然后放到一个集合中
        List<String> list = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.toList());
        list.forEach(System.out::println);
        System.out.println("-------------------------------------------");

        Set<String> set = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.toSet());
        set.forEach(System.out::println);
        System.out.println("-------------------------------------------");

        HashSet<String> hs = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.toCollection(HashSet::new));
        hs.forEach(System.out::println);
    }

    @Test
    public void test3() {
        Long count = employees.stream().collect(Collectors.counting());
        System.out.println(count);

        System.out.println("-------------------------------------------");

        Double salary1 = employees.stream().collect(Collectors.averagingDouble(Employee::getSalary));
        System.out.println(salary1);

        System.out.println("-------------------------------------------");

        Double salary2 = employees.stream().collect(Collectors.summingDouble(Employee::getSalary));
        System.out.println(salary2);

        System.out.println("-------------------------------------------");

        Optional<Employee> empMax = employees.stream().collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
        System.out.println(empMax.get());

        System.out.println("-------------------------------------------");

        Optional<Double> min = employees.stream()
                .map(Employee::getSalary)
                .collect(Collectors.minBy(Double::compare));
        System.out.println(min.get());
    }

    @Test
    public void test4() {
        //分组
        Map<Employee.Status, List<Employee>> m1 = employees.stream()
                .collect(Collectors.groupingBy(Employee::getStatus));
        System.out.println(m1);
    }

    @Test
    public void test5() {
        //多级分组
        Map<Employee.Status, Map<String, List<Employee>>> map = employees.stream()
                .collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy((e) -> {
                    if (e.getAge() <= 18) {
                        return "未成年";
                    } else if (e.getAge() < 21) {
                        return "青年";
                    } else {
                        return "老年";
                    }
                })));
        System.out.println(map);
    }

    @Test
    public void test6() {
        //分区
        Map<Boolean, List<Employee>> map = employees.stream().collect(Collectors.partitioningBy((e) -> e.getSalary() > 2222));
        System.out.println(map);
    }
    @Test
    public void test7() {
        DoubleSummaryStatistics dss=employees.stream().collect(Collectors.summarizingDouble(Employee::getSalary));
        System.out.println(dss);
    }
    @Test
    public void test8() {
        String str=employees.stream().map(Employee::getName).collect(Collectors.joining(","));
        System.out.println(str);
    }

}

实例

交易员类

import lombok.Data;

//交易员类
@Data
public class Trader {

    private String name;
    private String city;

    public Trader() {
    }

    public Trader(String name, String city) {
        this.name = name;
        this.city = city;
    }
}

交易类

import lombok.Data;

//交易类
@Data
public class Transaction {

	private Trader trader;
	private int year;
	private int value;

	public Transaction() {
	}

	public Transaction(Trader trader, int year, int value) {
		this.trader = trader;
		this.year = year;
		this.value = value;
	}

}

功能

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

import org.junit.Before;
import org.junit.Test;

public class TestTransaction {
	
	List<Transaction> transactions = null;
	
	@Before
	public void before(){
		// 四个交易员
		Trader raoul = new Trader("Raoul", "Cambridge");
		Trader mario = new Trader("Mario", "Milan");
		Trader alan = new Trader("Alan", "Cambridge");
		Trader brian = new Trader("Brian", "Cambridge");

		//交易列表
		transactions = Arrays.asList(
				new Transaction(brian, 2011, 300),
				new Transaction(raoul, 2012, 1000),
				new Transaction(raoul, 2011, 400),
				new Transaction(mario, 2012, 710),
				new Transaction(mario, 2012, 700),
				new Transaction(alan, 2012, 950)
		);
	}
	
	//1. 找出2011年发生的所有交易, 并按交易额排序(从低到高)
	@Test
	public void test1(){
		transactions.stream()
					.filter((t) -> t.getYear() == 2011)
					.sorted((t1, t2) -> Integer.compare(t1.getValue(), t2.getValue()))
					.forEach(System.out::println);
	}
	
	//2. 交易员都在哪些不同的城市工作过?
	@Test
	public void test2(){
		transactions.stream()
					.map((t) -> t.getTrader().getCity())
					.distinct()
					.forEach(System.out::println);
	}
	
	//3. 查找所有来自剑桥的交易员,并按姓名排序
	@Test
	public void test3(){
		transactions.stream()
					.filter((t) -> t.getTrader().getCity().equals("Cambridge"))
					.map(Transaction::getTrader)
					.sorted((t1, t2) -> t1.getName().compareTo(t2.getName()))
					.distinct()
					.forEach(System.out::println);
	}
	
	//4. 返回所有交易员的姓名字符串,按字母顺序排序
	@Test
	public void test4(){
		transactions.stream()
					.map((t) -> t.getTrader().getName())
					.sorted()
					.forEach(System.out::println);
		
		System.out.println("-----------------------------------");
		
		String str = transactions.stream()
					.map((t) -> t.getTrader().getName())
					.sorted()
					.reduce("", String::concat);
		
		System.out.println(str);
		
		System.out.println("------------------------------------");
		
		transactions.stream()
					.map((t) -> t.getTrader().getName())
					.flatMap(TestTransaction::filterCharacter)
					.sorted((s1, s2) -> s1.compareToIgnoreCase(s2))
					.forEach(System.out::print);
	}
	
	public static Stream<String> filterCharacter(String str){
		List<String> list = new ArrayList<>();
		
		for (Character ch : str.toCharArray()) {
			list.add(ch.toString());
		}
		
		return list.stream();
	}
	
	//5. 有没有交易员是在米兰工作的?
	@Test
	public void test5(){
		boolean bl = transactions.stream()
					.anyMatch((t) -> t.getTrader().getCity().equals("Milan"));
		
		System.out.println(bl);
	}
	
	
	//6. 打印生活在剑桥的交易员的所有交易额
	@Test
	public void test6(){
		Optional<Integer> sum = transactions.stream()
					.filter((e) -> e.getTrader().getCity().equals("Cambridge"))
					.map(Transaction::getValue)
					.reduce(Integer::sum);
		
		System.out.println(sum.get());
	}
	
	
	//7. 所有交易中,最高的交易额是多少
	@Test
	public void test7(){
		Optional<Integer> max = transactions.stream()
					.map((t) -> t.getValue())
					.max(Integer::compare);
		
		System.out.println(max.get());
	}
	
	//8. 找到交易额最小的交易
	@Test
	public void test8(){
		Optional<Transaction> op = transactions.stream()
					.min((t1, t2) -> Integer.compare(t1.getValue(), t2.getValue()));
		
		System.out.println(op.get());
	}

}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值