java的stream流

目录

0:在学习stream流之前回顾知识点

0.1:传统方式遍历集合

0.2:迭代器遍历集合

0.3:这两种方式的有优缺点

1:stream流的含义

2:stream流的优点

3:stream流使用

3.1:获取流

[3.2:中间方法 用于过滤、排序、聚合](#3.2:中间方法 用于过滤、排序、聚合)

3.3:终结方法


0:在学习stream流之前回顾知识点

下图是容器的类图,可以看到最上层的接口是迭代器,我们这里为什么了解迭代器呢?

接着往下看,我们遍历数组一般使用两种方式,一种是传统方式,一种是迭代器方式。当我们了解到了这两种方式的优缺点之后,我们再来学习流

0.1:传统方式遍历集合

传统遍历元素:直接通过索引遍历集合(如数组),客户端需要知道集合的内部结构(如数组长度),不推荐在里边删除元素。

java 复制代码
/**
     * 传统遍历元素
     */
    @Test
    public void T1(){
        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("c");
        list.add("d");
        //list的传统方式遍历 我们需要知道数组的长度
        for (int i = 0; i < list.size(); i++) {
            System.out.println("传统遍历list:"+list.get(i));
        }
    }


    /**
     * 传统for遍历元素删除,这种方法不推荐
     */
    @Test
    public void T11(){
        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("c");
        list.add("d");
        //list的传统方式遍历 我们需要知道数组的长度
        for (int i = 0; i < list.size(); i++) {
            //在for循环中删除元素c,会导致后边的元素前移,从而漏掉下一个元素,所以输出结果还有c
            if (list.get(i).equals("c")){
                list.remove(i);
                //list.remove(s); 错误方法 ConcurrentModificationException

            }
        }
        System.out.println(list);
    }

0.2:迭代器遍历集合

1:我们先看一下迭代器的方法,Java 的集合框架(如 List、Set)均实现了 Iterator 接口,通过iterator() 方法返回迭代器。迭代器被归类java设计模式里面的 行为型设计模式 (Behavioral Design Pattern),定义了 对象之间的交互方式

它的核心思想是:解耦遍历逻辑,我们不关心他们具体的数据结构

适用于set、list、map。也就是说我们不关心他们的数据结构,只管用迭代器遍历就行,可以删除数据。

它通常包含以下核心方法:

hasNext():判断是否还有下一个元素。

next():获取下一个元素。

remove()(可选):删除当前元素。

2:迭代器遍历元素

删除元素的强制模数(修改次数)=预期模数,删除数据的时候回判断模数是否等于预期模数。保证了删除是数据安全。

0.3:这两种方式的有优缺点

传统方式遍历:需要根据索引下标遍历集合,需要知道集合的长度数据

迭代器方式遍历:解耦数据结构,通用迭代器遍历。不关心数据结构,提供了同一的访问接口,都是迭代器,缺点即使增加了额外的迭代器类

1:stream流的含义

stream流就像一种更高阶的迭代器,与传统的迭代器不一样,流不存储数据,只是代表了一个计算过程,在这个过程中对数据进行操作。比如过滤、排序、聚合操作。流就像一个管道,在这个管道中对数据操作、按照一定的规则流动。比传统迭代器多了过滤、排序、聚合等操作,功能更丰富。

2:stream流的优点

流的作用主要体现在以下几个方面:

函数式编程风格:流API提供了一套丰富的函数式编程特性,使得代码更简洁、可读性更强。我们可以用非常少的代码处理复杂的逻辑。

无状态操作:流的操作不会改变原始数据集合,它们是无状态的。这就像是音乐家们的乐器,演奏结束后,乐器仍然是原始的状态,没有被改变。

3:stream流使用

3.1:获取流

java 复制代码
/**
 * 在使用Stream流过程中
 * 1:获取流
 * 2:处理流
 * 2.1:中间方法
 * 2.2:终结方法
 */
public class Steam获取流1 {


    //1:list获取流 list.stream()
    @Test
    public void t1() {
        List<String> list = new ArrayList<>();
        list.add("1");
        list.add("2");
        list.add("3");
        list.add("4");
        list.add("5");
        list.add("6");
        list.add("");
        list.add(null);
        Stream<String> stream = list.stream();

        stream.forEach(System.out::println);//终结方法
    }


    //2:set获取流 set.stream()
    @Test
    public void t2() {
        Set<String> set = new HashSet<>();
        set.add("1");
        set.add("2");
        set.add("3");
        set.add("1");
        set.add("4");
        set.add("5");
        Stream<String> stream = set.stream();
        stream.forEach(System.out::println);

    }

    //3:map获取流 map.keySet().stream()
    @Test
    public void t3() {
        Map<String, Integer> map = new HashMap<>();
        map.put("11", 1);
        map.put("22", 2);
        map.put("33", 3);
        map.put("44", 4);
        System.out.println("=======");
        Stream<String> stream = map.keySet().stream();
        stream.forEach(System.out::println);
        System.out.println("=======");
        Stream<Map.Entry<String, Integer>> stream1 = map.entrySet().stream();
        stream1.forEach(entry -> System.out.println(entry.getKey() + ":" + entry.getValue()));

    }


    //4:数组获取流 Arrays.stream()
    @Test
    public void t4() {
        int[] ints = new int[]{1, 2, 3, 4, 5};
        Arrays.stream(ints).forEach(System.out::println);
        System.out.println("================");
        String[] strings = {"1", "2", "3", "4"};
        Stream<String> stream = Arrays.stream(strings);
        stream.forEach(System.out::println);
    }


    //5:stream流直接创建 Stream.of()
    @Test
    public void t5() {
        Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
        stream.forEach(System.out::println);

        System.out.println("==============");
        Stream<String> stream1 = Stream.of("a","b","c","d");
        stream1.forEach(System.out::println);

        Integer[] ints = {1, 2, 3, 4, 5};
        String[] strings = {"1", "2", "3", "4"};

        Stream.of(ints).forEach(System.out::println);
        System.out.println("=============");
        Stream.of(strings).forEach(System.out::println);

    }
}

3.2:中间方法 用于过滤、排序、聚合

java 复制代码
/**
     * stream流体验 过滤
     * 代码简单,不改变原始流 
     */
    @Test
    public void t1(){
        List<Person> peoples = List.of(
                new Person("北京", 15, "Jack1"),
                new Person("洛阳", 18, "Jack2"),
                new Person("深圳", 30, "Jack3"),
                new Person("杭州", 45, "Jack4"),
                new Person("青岛", 50, "Jack5")
        );
        //传统for循环,需要过滤age大于18的,代码比较多
        List<Person> people18=new ArrayList<>();
        for (Person people : peoples) {
            System.out.println("增强for:"+people);
            if (people.getAge()>18){
                people18.add(people);
            }
        }
        //Stream流初体验,filter过滤年龄大于18的person,函数式编程
        //代码简单,返回新的集合,原来的集合不变,这就是无状态,不改变原始数据
        List<Person> newlist = peoples.stream()
                .filter(person -> person.getAge() > 18)
                .toList();
        newlist.forEach(System.out::println);//新的集合
        System.out.println("=====");
        peoples.forEach(System.out::println);//原始集合不变
    }




 //1.1:filter 中间方法 过滤
    @Test
    public void filter1() {
        List<Person> people = List.of(
                new Person("北京", 15, "Jack1"),
                new Person("洛阳", 18, "Jack2"),
                new Person("深圳", 30, "Jack3"),
                new Person("杭州", 45, "Jack4"),
                new Person("青岛", 50, "Jack5"),
                new Person("青岛", 50, "Jack5")
        );
        List<Person> list = people.stream().filter(new Predicate<Person>() {
            @Override
            public boolean test(Person person) {
                //返回值为true,数据留下,否则抛弃
                return person.getAge() > 30;
            }
        }).toList();
        list.forEach(System.out::println);

        System.out.println("========简化写法========");
        people.stream()
                .filter(p -> p.getAge() > 30)
                .filter(person -> person.getName().contains("Jack5"))
                .forEach(System.out::println);

    }

    //1.2:filter 中间方法 过滤
    @Test
    public void filter2() {
        List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("张三丰");
        list.add("张三丰");
        list.add("张强");
        list.add("周芷若");
        list.add("赵敏");
        Stream<String> stringStream = list.stream()
                .filter(name -> name.startsWith("张"));
        stringStream.forEach(System.out::println);

        //报错,一旦使用了终结方法,stream就会被关闭
        //stringStream.filter(name->name.startsWith("张三")).forEach(System.out::println);
    }


    //2:limit 中间方法 指定范围
    @Test
    public void limit() {
        List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("张三丰");
        list.add("张三丰");
        list.add("张强");
        list.add("周芷若");
        list.add("赵敏");
        list.stream().limit(3).forEach(System.out::println);
        //forEach 是终结方法
    }

    //3:skip 中间方法 跳过2个元素
    @Test
    public void spip() {
        List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("张三丰1");
        list.add("张三丰2");
        list.add("张强");
        list.add("周芷若");
        list.add("赵敏");
        list.stream().skip(2).forEach(System.out::println);
        System.out.println("===============");
        list.stream().limit(3).skip(2).forEach(System.out::println);
    }

    //4:distinct 中间方法 去重复元素
    @Test
    public void distinct() {
        List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("张三丰");
        list.add("张三丰");
        list.add("张强");
        list.add("周芷若");
        list.add("赵敏");
        list.stream().distinct().forEach(System.out::println);
    }

    //5:concat 中间方法 合并两个流的数据
    @Test
    public void concat() {
        Stream<String> stringStream1 = Stream.of("1", "2", "3", "a");
        Stream<String> stringStream2 = Stream.of("a", "b", "c");
        Stream<String> concat = Stream.concat(stringStream1, stringStream2);
        concat.distinct().forEach(System.out::println);

        //.distinct().forEach(System.out::println);
    }

    //6:map 中间方法 转换流的数据类型
    @Test
    public void map() {
        List<String> list = new ArrayList<>();
        Collections.addAll(list, "张三1-21", "张三2-22", "张三3-23", "张三4-24", "张三5-25");

        System.out.println("========分割线=======");
        list.stream().map(new Function<String, String>() {
            @Override
            public String apply(String s) {
                System.out.println("传递得到:"+s);
                String[] split = s.split("-");
                String name=split[0];
                String age=split[1];
                return age;
            }
        }).forEach(System.out::println);

        System.out.println("========分割线,简化写法=======");
        list.stream()
                .map(s -> Integer.parseInt(s.split("-")[1]))
                .forEach(System.out::println);


    }

3.3:终结方法

java 复制代码
/**
 * 在使用Stream流过程中
 * 1:获取流
 * 2:处理流
 * 2.1:中间方法
 * 2.2:终结方法
 */
public class Steam终结方法3 {


    //1:forEach 终结方法,
    @Test
    public void forEach() {
        List<Person> people = List.of(
                new Person("北京", 15, "Jack1"),
                new Person("洛阳", 18, "Jack2"),
                new Person("深圳", 30, "Jack3"),
                new Person("杭州", 45, "Jack4"),
                new Person("青岛", 50, "Jack5"),
                new Person("青岛", 50, "Jack5")
        );
       people.stream().forEach(new Consumer<Person>() {
           @Override
           public void accept(Person person) {
               System.out.println(person);
           }
       });

        System.out.println("======终结方法======");
        people.stream().forEach(person -> System.out.println(person));
        System.out.println("======终结方法======");
        people.stream().forEach(System.out::println);

    }



    //2:count 终结方法,
    @Test
    public void count() {
        List<Person> people = List.of(
                new Person("北京", 15, "Jack1"),
                new Person("洛阳", 18, "Jack2"),
                new Person("深圳", 30, "Jack3"),
                new Person("杭州", 45, "Jack4"),
                new Person("青岛", 50, "Jack5"),
                new Person("青岛", 50, "Jack5")
        );
        long count = people.stream().count();
        System.out.println("长度:"+count);

    }

    //2:toArray 终结方法 准换成数组
    @Test
    public void toArray() {
        List<Person> people = List.of(
                new Person("北京", 15, "Jack1"),
                new Person("洛阳", 18, "Jack2")

        );
        Object[] array = people.stream().toArray();
        System.out.println("长度:"+array.length);
        for (Object o : array) {
            System.out.println(o);
        }

    }

    //3:toList toSet  toMap
    //map的
    // 终结方法 转换成list
    @Test
    public void toList(){
        List<String> list = new ArrayList<>();
        Collections.addAll(list, "张三1-男-21", "张三1-男-21","张三2-男-22", "丽丽3-女-23", "张三4-男-24", "丽丽5-女-25");

        System.out.println("======toList=====");
        List<String> list1 = list.stream()
                .filter(s -> "男".equals(s.split("-")[1]))
                .toList();
        list1.forEach(System.out::println);

        System.out.println("======toSet=====");
        Set<String> set = list.stream()
                .filter(s -> "男".equals(s.split("-")[1]))
                .collect(Collectors.toSet());

        set.forEach(System.out::println);

        System.out.println("======toMap=====");
        Map<String, String> map = list.stream()
                .filter(s -> "男".equals(s.split("-")[1]))
                .distinct() //必须去重,key不能重复
                .collect(Collectors.toMap(n -> n.split("-")[0], n -> n.split("-")[1]));
        map.forEach((k, v) -> System.out.println(k + "=" + v));

    }




}
相关推荐
Fireworkitte1 小时前
Apache POI 详解 - Java 操作 Excel/Word/PPT
java·apache·excel
weixin-a153003083161 小时前
【playwright篇】教程(十七)[html元素知识]
java·前端·html
DCTANT1 小时前
【原创】国产化适配-全量迁移MySQL数据到OpenGauss数据库
java·数据库·spring boot·mysql·opengauss
Touper.2 小时前
SpringBoot -- 自动配置原理
java·spring boot·后端
黄雪超2 小时前
JVM——函数式语法糖:如何使用Function、Stream来编写函数式程序?
java·开发语言·jvm
ThetaarSofVenice2 小时前
对象的finalization机制Test
java·开发语言·jvm
思则变2 小时前
[Pytest] [Part 2]增加 log功能
开发语言·python·pytest
漫谈网络2 小时前
WebSocket 在前后端的完整使用流程
javascript·python·websocket
专注VB编程开发20年3 小时前
开机自动后台运行,在Windows服务中托管ASP.NET Core
windows·后端·asp.net
望获linux3 小时前
【实时Linux实战系列】CPU 隔离与屏蔽技术
java·linux·运维·服务器·操作系统·开源软件·嵌入式软件