Java Stream API

本文详细介绍了Java 8的Stream API,包括其核心概念、用途、与传统集合的区别,以及如何创建和操作Stream。通过实例展示了Stream的中间操作如筛选、映射和排序,以及终止操作如匹配、查找和归约。Stream API提供了高效处理数据的方式,适用于多种数据源,尤其在大数据和并发场景下表现优异。
Stream 是java8中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,
可以执行非常复杂的查找,过滤,映射数据等操作。使用Stream API对集合数据进行操作,就类似于使用SQL执行的数据库查询。
简而言之,Stream API提供了一种高效且易于使用的处理数据的方式。

为什么要使用Stream API?
实际开发中,有许多数据源来自mysql oracle等关系型数据库,随着现在应用场景的需要,MongDB REDIS这样nosql数据库也用得越来越多,
这些nosql数据库中的数据就需要java层面的处理。

Stream和Collection集合的区别:Collection是一种静态的内存数据结构,而Stream是和计算相关的。
前者主要是面向内存,后者主要是面向CPU。

Stream到底是干什么的?
用于操作数据源(集合,数组)所生成的元素序列。集合讲的是数据,Stream讲得是计算。

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

Stream操作的三大步骤:
(1)创建Stream:一个数据源(如集合、数组)获取一个流
(2)中间操作:一个中间操作链,对数据源的数据进行处理
(3)终止操作:一旦执行终止操作就执行中间操作链,并产生结果,之后不会再被使用。

创建Stream的几大方式:

package com.sf.javalearning0929;

import org.junit.Test;

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

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

为什么要使用Stream API?
实际开发中,有许多数据源来自mysql oracle等关系型数据库,随着现在应用场景的需要,MongDB REDIS这样nosql数据库也用得越来越多,
这些nosql数据库中的数据就需要java层面的处理。

Stream和Collection集合的区别:Collection是一种静态的内存数据结构,而Stream是和计算相关的。
前者主要是面向内存,后者主要是面向CPU。

Stream到底是干什么的?
用于操作数据源(集合,数组)所生成的元素序列。集合讲的是数据,Stream讲得是计算。

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

Stream操作的三大步骤:
(1)创建Stream:一个数据源(如集合、数组)获取一个流
(2)中间操作:一个中间操作链,对数据源的数据进行处理
(3)终止操作:一旦执行终止操作就执行中间操作链,并产生结果,之后不会再被使用。


 */
public class StreamAptLearning01 {
    //创建Stream方式一:通过集合
    @Test
    public void test01(){
        List<Employee> employees = EmployeeData.getEmployees();
        //default Stream<E> stream(): 返回一个顺序流
        Stream<Employee> empstream = employees.stream();
        //default Stream<E> parallelStream():返回一个并行流
        Stream<Employee> empparallelStream = employees.parallelStream();
    }

    //创建Stream方式二:通过数组
    //Java8中的Arrays的静态方法stream()可以获取数组流
    //static <T> Stream<T> straem(T[] array)
    @Test
    public void test02(){
        int[] arr = new int[]{2,3,4};
        //调用Arrays类的static <T> Stream<T> straem(T[] array):返回一个流
        IntStream stream = Arrays.stream(arr);

        Employee e1 = new Employee("we",23,1,2222);
        Employee e2 = new Employee("are",24,2,2222);
        Employee[] arr1 = new Employee[]{e1,e2};
        Stream<Employee> stream1 = Arrays.stream(arr1);
    }

    //创建Stream方式三:通过stream的of()方法
    @Test
    public void test03(){
        Stream<Integer> integerStream = Stream.of(1, 2, 3);
    }

    //创建Stream方式四:创建无限流
    @Test
    public void test04(){
        //迭代
        //public static<T> Stream<T> iterate(final T seed,final UnaryOperator<T> f)
        Stream.iterate(0,t -> t + 2).limit(10).forEach(System.out :: println);

        //生成
        //public static<T> Stream<T> generate(Supplier<T> s)
        Stream.generate(Math :: random).limit(10).forEach(System.out :: println);
    }

}

class EmployeeData{
    public static List<Employee> getEmployees(){
        List<Employee> list = new ArrayList<>();

        list.add(new Employee("张3",24,01,3000));
        list.add(new Employee("张4",34,02,4000));
        list.add(new Employee("张5",54,03,5000));
        list.add(new Employee("张6",64,04,6000));
        list.add(new Employee("张7",14,05,9000));

        return list;
    }
}


Stream的中间操作:

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

Stream的中间操作:
(1)筛选与切片
(2)映射
(3)排序

package com.sf.javalearning0929;

import org.junit.Test;

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

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

Stream的中间操作:
(1)筛选与切片
(2)映射
(3)排序

 */
public class StreamApiLearning02 {
    @Test
    //筛选与切片
    public void test01(){
        List<Employee> list = EmployeeData.getEmployees();
        //filter(Predicate p) 接收lambda,从流中排除某些元素
        list.stream().filter(employee -> employee.getAge() > 34).forEach(System.out :: println);
        System.out.println("***************************");

        //limit(n)-截断流,使其元素数量不超过指定数量
        list.stream().limit(2).forEach(System.out :: println);
        System.out.println("********************************");

        //skip(n) 跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个则返回一个空流
        list.stream().skip(1).forEach(System.out :: println);
        System.out.println("********************************");

        //distinct() 筛选,通过流所生成元素的hashCode()和equals()去除重复元素
        list.stream().distinct().forEach(System.out :: println);
    }

    @Test
    //映射
    //map(Function f) --接收一个函数作为参数,将元素转换成其他形式或提取信息,该函数会被应用到每一个元素上面并将其映射为一个新的元素
    public void test02(){
        List<String> list = Arrays.asList("aa", "bb", "cc");
        list.stream().map(s -> s.toUpperCase()).forEach(System.out :: println);

        List<Employee> empList = EmployeeData.getEmployees();
        empList.stream().map(s -> s.getName()).filter(a -> a.length() > 1).distinct().forEach(System.out :: println);
    }

    //flatMap(Function f) 和map(Function f)的区别

    @Test
    //排序
    //sorted()  产生一个新流,其中按自然顺序排序
    //sorted(Comparator com) 产生一个新流,其中按比较器顺序排序
    public void test03(){
        //sorted()  产生一个新流,其中按自然顺序排序
        List<Integer> list = Arrays.asList(1,2,3,4);
        list.stream().sorted().forEach(System.out :: println);

       List<Employee> employeeslist = EmployeeData.getEmployees();
        //这样会报错,因为Employee类没有实现Comparable接口
        // employeeslist.stream().sorted().forEach(System.out :: println);

        //sorted(Comparator com) 产生一个新流,其中按比较器顺序排序
        employeeslist
                .stream()
                .sorted((e1,e2) -> Integer.compare(e1.getAge(),e2.getAge()))
                .distinct()
                .forEach(System.out :: println);


    }
}

终止操作
(1):匹配和查找
(2):归约
(3):收集

import org.junit.Test;

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

/*
Stream的终止操作:
(1):匹配和查找
(2):归约
(3):收集
 */
public class StreamLearning03 {
    //匹配和查找
    @Test
    public void test01(){
        List<Employee> employeeslist = EmployeeData.getEmployees();
        //allMatch(Predicate p) 检查是否匹配所有元素
        System.out.println(employeeslist.stream().allMatch(e -> e.getAge() > 18));
        //anyMatch(Predicate p) 检查是否至少匹配一个元素
        System.out.println(employeeslist.stream().anyMatch(e -> e.getSalary() > 1000));
        //nonMatch(Predicate p) 检查是否没有匹配的元素
        System.out.println(employeeslist.stream().noneMatch(e -> e.getName().startsWith("3")));
        //findFirst() 返回第一个元素
        System.out.println(employeeslist.stream().findFirst());
        //findAny 返回任意一元素
        System.out.println(employeeslist.stream().findAny());
        //count 返回流中元素的总个数
        System.out.println(employeeslist.stream().count());
        //max(Comparator c)返回流中最大元素
        System.out.println(employeeslist.stream().map(e -> e.getSalary()).max((e1,e2) -> Integer.compare(e1,e2)));
        //min(Comparator c)返回流中最小元素
        System.out.println(employeeslist.stream().min((e1, e2) -> Integer.compare(e1.getSalary(), e2.getSalary())));
        //forEach(Consumer c)内部迭代
        employeeslist.stream().forEach(System.out::println);
    }

    //归约
    @Test
    public void test02(){
        //reduce(T identity, BinaryOperator) 可以将流中的元素反复结合起来,得到一个值,返回一个T

        //计算1-10的和
        List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
        System.out.println(list.stream().reduce(0, (a, b) -> Integer.sum(a, b)));

        //计算所有员工工资的总和
        List<Employee> employeeslist = EmployeeData.getEmployees();
        System.out.println(employeeslist.stream().map(e -> e.getSalary()).reduce((e1, e2) -> (Integer.sum(e1,e2))));

        //可以拆分为以下几步
        Stream<Integer> salarySream = employeeslist.stream().map(e -> e.getSalary());
        Optional<Integer> salaries = salarySream.reduce((e1, e2) -> Integer.sum(e1, e2));
        System.out.println(salaries);


        List<Employee> collect = employeeslist.stream().filter(e -> e.getSalary() > 2000).collect(Collectors.toList());
        collect.forEach(System.out::println);
    }

    //收集
    @Test
    public void test03(){

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值