其他分享
首页 > 其他分享> > 四十六、Stream流

四十六、Stream流

作者:互联网

在Java 8中,得益于Lambda所带来的函数式编程,引入了一个全新的Stream概念,用于解决已有集合类库既有的弊端。流式思想类似于工厂车间的“生产流水线

1、引入

1.1 传统集合的多步遍历代码

几乎所有的集合(如Collection接口或Map接口等)都支持直接或间接的遍历操作。而当我们需要对集合中的元素进行操作的时候,除了必需的添加、删除、获取外,最典型的就是集合遍历。

public class Demo01ForEach {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("张强");
        list.add("张三丰");
        for (String name : list) {
          	System.out.println(name);
        }
    }  
}

1.2 循环遍历的弊端

为什么使用循环?因为要进行遍历。但循环是遍历的唯一方式吗?遍历是指每一个元素逐一进行处理,而并不是从第一个到最后一个顺次处理的循环

public class Demo02NormalFilter {
  	public static void main(String[] args) {
      	List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("张强");
        list.add("张三丰");

        List<String> zhangList = new ArrayList<>();
        for (String name : list) {
            if (name.startsWith("张")) {
              	zhangList.add(name);
            }
        }

        List<String> shortList = new ArrayList<>();
        for (String name : zhangList) {
            if (name.length() == 3) {
              	shortList.add(name);
            }
        }

        for (String name : shortList) {
          	System.out.println(name);
        }
    }
}

这段代码中含有三个循环,每一个作用不同:

  1. 首先筛选所有姓张的人;
  2. 然后筛选名字有三个字的人;
  3. 最后进行对结果进行打印输出。

1.3 Stream的更优写法

public class Demo03StreamFilter {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        //List<String> list = new ArrayList<>(List.of("张无忌","周芷若","赵敏"));
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("张强");
        list.add("张三丰");

        list.stream()
          	.filter(s -> s.startsWith("张"))
            .filter(s -> s.length() == 3)
            .forEach(System.out::println);
    }
}

直接阅读代码的字面意思即可完美展示无关逻辑方式的语义:获取流、过滤姓张、过滤长度为3、逐一打印。代码中并没有体现使用线性循环或是其他任何算法进行遍历,我们真正要做的事情内容被更好地体现在代码中。

2、Stream的四类方法

3、获取Stream流方式

java.util.stream.Stream<T>是Java 8新加入的最常用的流接口。

获取一个流非常简单,有以下几种常用的方式:

3.1 根据Collection获取流

首先,java.util.Collection接口中加入了default方法stream用来获取流,所以其所有实现类均可获取流。

import java.util.*;
import java.util.stream.Stream;

public class Demo04GetStream {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        // ...
        Stream<String> stream1 = list.stream();

        Set<String> set = new HashSet<>();
        // ...
        Stream<String> stream2 = set.stream();

        Vector<String> vector = new Vector<>();
        // ...
        Stream<String> stream3 = vector.stream();
    }
}

3.2 根据Map获取流

java.util.Map接口不是Collection的子接口,且其K-V数据结构不符合流元素的单一特征,所以获取对应的流需要分key、value或entry等情况:

import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;

public class Demo05GetStream {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        // ...
        Stream<String> keyStream = map.keySet().stream();
        Stream<String> valueStream = map.values().stream();
        Stream<Map.Entry<String, String>> entryStream = map.entrySet().stream();
    }
}

3.3 根据数组获取流

如果使用的不是集合或映射而是数组,由于数组对象不可能添加默认方法,所以Stream接口中提供了静态方法of;也可以使用Arrays 下面的Stream流方法

import java.util.stream.Stream;

public class Demo06GetStream {
    public static void main(String[] args) {
        String[] array = { "张无忌", "张翠山", "张三丰", "张一元" };
        
        Arrays.stream(arr)
        // 或者
        // Stream<String> stream = Stream.of(array);
    }
}

of() 方法的参数其实是一个可变参数,所以支持数组

//of另一种使用,可以根据相同数据获取流
Strean.of("123","456","789");

4、中间方法

5、终结方法

6、收集方法

对流中的数据进行操作,是不能修改原有的集合、数组 数据的

6.1 Stream流的收集操作

使用Stream流的方式操作完毕之后,我想把流中的数据起来,该怎么办呢?

Stream流提供collect方法,其参数需要一个java.util.stream.Collector<T,A, R>接口对象来指定收集到哪种集合中。幸运的是,java.util.stream.Collectors类提供一些方法,可以作为Collector接口的实例

Stream流的收集方法

工具类Collectors提供了具体的收集方式

6.2 收集到单例集合中

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

public class Demo15StreamCollect {
    public static void main(String[] args) {
        Stream<String> stream = Stream.of("10", "20", "30", "40", "50");
        List<String> list = stream.collect(Collectors.toList());
        Set<String> set = stream.collect(Collectors.toSet());
    }
}

6.3 收集到双列集合中

public class StreamDemo7 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        // 添加元素
        list.add("zhangsan,23");
        list.add("lisi,24");
        list.add("wangwu,25");

        // 需求1 : 年龄大于等于24岁的人
        /*
            filter方法中的s 代表的是每一个字符串 zhangsan,23  ; lisi,24 ; wangwu,25
         */

        list.stream().filter(s -> {
            String[] strs = s.split(",");// {"名字" , "年龄"}
            // 把年龄转成int类型的数据
            int age = Integer.parseInt(strs[1]);
            return age >= 24;
        }).collect(Collectors.toMap( // toMap要两个参数 , 两个Function类型的数据 , Function是一个函数式接口 , 那么我们只要传入两个Lambda表达式
                // s代表的是流中的每一个数据 lisi,24
                // 此Lambda要返回的是Map集合的键
                (String s)->{ return s.split(",")[0]; }
                ,
                // 此Lambda要返回的是Map集合的值
                (String s)->{ return s.split(",")[1]; }
                ));
    }
}

6.4 收集到数组中

Stream提供toArray方法来将结果放到一个数组中,返回值类型是Object[]的:

import java.util.stream.Stream;

public class Demo16StreamArray {
    public static void main(String[] args) {
        Stream<String> stream = Stream.of("10", "20", "30", "40", "50");
        Object[] objArray = stream.toArray();
    }
}

标签:Stream,stream,list,add,public,四十六,String
来源: https://www.cnblogs.com/6ovo6/p/14969217.html