java8Stream流的学习

StreamApi

流(Stream)是什么?

是数据渠道,用于操作数据源(集合 ,数组等)所生成的元素序列

集合讲的是数据,流讲的是计算

注意:

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

Stream 操作的三歌步骤:

  • 创建 Stream

    • 一个数据源(集合、数组)获取流
  • 中间操作

    • 对数据流进行处理
  • 终止操作

    • 产生结果
1、创建Stream流的方式:
  • 可用通过collection系列的集合提供的stream() 或parallelStream() 并行流
  • 通过Arrays中的静态方法stream()
  • 通过Stream中的静态方法of()
  • 创建无限流
@Test
//创建流的方式
public void test1() {
//1、可用通过collection系列的集合提供的stream() 或parallelStream() 并行流
ArrayList<String> list = new ArrayList<>();
Stream<String> stream = list.stream();
//2、通过Arrays中的静态方法stream()
int[] ints = new int[10];
IntStream stream1 = Arrays.stream(ints);
//3、通过Stream中的静态方法of()
Stream<String> stream2 = Stream.of("aa", "bb", "c");
//4、创建无限流
Stream<Integer> stream3 = Stream.iterate(0, (x) -> x + 1);
}
2、中间操作

中间操作不会执行任何的处理,只有遇到终止操作时,流才会一次性的全部处理。(惰性求值)

  • 筛选与切片

    • filter 接收lambda,从流中排除某些元素
    • limit 截断流,使其元素不超过给定的数值
    • skip(n) 跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit互补
    • distinct 通过流中元素的hashCode() 和equals() 去除重复元素
    List<Employee> employees = Arrays.asList(
    new Employee("张三", 18, 3000),
    new Employee("李四", 18, 3000),
    new Employee("张三", 45, 8700),
    new Employee("王五", 26, 4500),
    new Employee("麻子", 30, 2700),
    new Employee("田七", 15, 200)
    );
    @Test
    public void test2(){
    employees.stream()
    //过滤拿到员工年龄超过20岁的
    .filter((e) -> e.getAge() > 20)
    //Employee{name='张三', age=45, salary=8700.0}
    //Employee{name='王五', age=26, salary=4500.0}
    //Employee{name='麻子', age=30, salary=2700.0}
    //取出前两个元素
    .limit(2)
    //Employee{name='张三', age=45, salary=8700.0}
    //Employee{name='王五', age=26, salary=4500.0}
    //跳过前一个元素
    .skip(1)
    //Employee{name='王五', age=26, salary=4500.0}
    //去除重复(这里没有重复的)
    .distinct()
    //终止操作
    .forEach(System.out::println);
    }
  • 映射

    • map 接收lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的流。
    • flatMap 接收一个函数作为参数,将流中的每个值换成另一个流,然后把所有的流连接成一个流。
    @Test
    public void test3(){
    List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd");
    list.stream()
    //把字符转大写
    .map((s)-> s.toUpperCase(Locale.ROOT))
    //AAA BBB CCC DDD
    .forEach(System.out::println);
    //获取数组中每个元素的字符
    list.stream()
    .map(StreamApiTest::filterString)
    .forEach(sm -> sm.forEach(System.out::println));
    // a a a b b b c c c d d d
    Stream<Stream<Character>> streamStream = list.stream()
    .map(StreamApiTest::filterString);
    streamStream.forEach((sm) -> sm.forEach(System.out::println));
    // a a a b b b c c c d d d
    //用这个方法相当于上面的处理方法
    list.stream()
    .flatMap(StreamApiTest::filterString)
    .forEach(System.out::println);
    // a a a b b b c c c d d d
    }
    //将字符串转化成字符流
    public static Stream<Character> filterString(String str){
    ArrayList<Character> list = new ArrayList<>();
    for (char c : str.toCharArray()) {
    list.add(c);
    }
    return list.stream();
    }
  • 排序

    • sorted() 自然排序( 按照comparable)比如String 中的comparaTo (实现了comparable接口的类)
    • sorted( Comparator) 定制排序 (自己写的conparator排序)
    @Test
    public void test4() {
    List<String> list = Arrays.asList("aaa", "ccc", "bbb", "ddd");
    list.stream()
    //按照String中的实现了comparable的排序规则
    .sorted()
    .forEach(System.out::println);
    // aaa bbb ccc ddd
    employees.stream()
    //按照自己写的排序规则来排序
    .sorted((e1,e2)-> Integer.compare(e1.getAge(),e2.getAge()))
    .forEach(System.out::println);
    //Employee{name='田七', age=15, salary=200.0}
    //Employee{name='张三', age=18, salary=3000.0}
    //Employee{name='李四', age=18, salary=3000.0}
    //Employee{name='王五', age=26, salary=4500.0}
    //Employee{name='麻子', age=30, salary=2700.0}
    //Employee{name='张三', age=45, salary=8700.0}
    }
3、终止操作
  • 查找与匹配

    • allMatch 检查是否匹配所有元素
    • anyMatch 检查 是否至少匹配一个元素
    • noneMatch 检查是否没有匹配所有元素
    • findFirst 返回第一个元素
    • **findAny ** 返回当前流中任意元素
    • count 返回流中的总个数
    • max 返回流中最大值
    • min 返回流中最小值
    @Test
    public void test5(){
    //判断是不是年龄都是18岁
    boolean b = employees.stream()
    .allMatch((e) -> e.getAge().equals(18));
    System.out.println(b); //false
    //判断是否有是18岁的
    boolean b1 = employees.stream()
    .anyMatch((e) -> e.getAge().equals(18));
    System.out.println(b1); //true
    //判断是不是没有20岁的
    boolean b2 = employees.stream()
    .noneMatch((e) -> e.getAge().equals(20));
    System.out.println(b2); //true
    //找出工资最低的那个
    //Optional四个容器类,可以避免空指针异常
    Optional<Employee> first = employees.stream()
    .sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))
    .findFirst();
    System.out.println(first.get()); //Employee{name='田七', age=15, salary=200.0}
    //随便找一个年龄为18的
    Optional<Employee> any = employees.stream()
    .filter((e) -> e.getAge().equals(18))
    .findAny();
    System.out.println(any.get()); //Employee{name='张三', age=18, salary=3000.0}
    //查看list中有多少个元素
    long count = employees.stream()
    .count();
    System.out.println(count); //6
    //获取年龄最大的
    Optional<Employee> max = employees.stream()
    .max((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge()));
    System.out.println(max.get()); //Employee{name='张三', age=45, salary=8700.0}
    //获取年龄最小的
    Optional<Employee> min = employees.stream()
    .min((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge()));
    System.out.println(min.get()); //Employee{name='田七', age=15, salary=200.0}
    }
  • 归约

    • reduce(T identity, BinaryOperator) 可以将流中元素反复结合起来,得到一个值
    @Test
    public void test6(){
    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    //对集合元素求和
    Integer reduce = list.stream()
    .reduce(0, (x, y) -> x + y);
    System.out.println(reduce); //55
    //求出工资总和
    Optional<Double> salary = employees.stream()
    .map(Employee::getSalary)
    .reduce(Double::sum);
    System.out.println(salary.get()); //22100.0
    }

    **map和reduce的连接通常称为map-reduce模式,Google 用它来进行网络搜索而出名

  • 收集

    • collect 将流转换为其他形式,接收一个collector接口的实现,用于给Stream中元素汇总的方法
    @Test
    public void test7(){
    //将所有的名字放到一个集合中
    List<String> list = employees.stream()
    .map(Employee::getName)
    .distinct()
    .collect(Collectors.toList());
    System.out.println(list.toString()); //[张三, 李四, 王五, 麻子, 田七]
    //可以进行分组 (按年龄分组)
    Map<Integer, List<Employee>> collect = employees.stream()
    .collect(Collectors.groupingBy(Employee::getAge));
    System.out.println(collect);
    //{18=[Employee{name='张三', age=18, salary=3000.0}, Employee{name='李四', age=18, salary=3000.0}], 26=[Employee{name='王五', age=26, salary=4500.0}], 45=[Employee{name='张三', age=45, salary=8700.0}], 30=[Employee{name='麻子', age=30, salary=2700.0}], 15=[Employee{name='田七', age=15, salary=200.0}]}
    }

    collect功能强大,可以转换为很多的形式

posted @   浪上了天  阅读(74)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示