Java Stream流 一把梭!

83 阅读5分钟

简介

Stream流作用

结合Lambda表达式,简化集合、数组的操作

Stream流的使用步骤

  1. 先得到一条Stream流,将数据放上去
  2. 使用中间方法对流水线上的数据进行操作
  3. 使用终结方法对流水线上的数据进行操作

获取Stream流

获取方式方法名说明
单列集合default Stream<E> stream()Collection中的默认方法
双列集合需要转换成单列集合才能获取Stream流
数组public static<T> Stream<T> stream(T[] array)Arrays工具类中的静态方法
零散数据public static<T> Stream<T> of(T... values)Stream接口中的静态方法

单列集合获取Stream流

public static void main(String[] args) {
    ArrayList<String> list = new ArrayList<>();
    // 向list中添加数据
    Collections.addAll(list,"a","b","c");
    // 1. 获取流
    // 2. 调用流的forEach方法
    // 3. 使用lambda表达式,对每一个参数s,执行打印操作
    list.stream().forEach(s -> System.out.println(s));
}

双列集合获取Stream流

public static void main(String[] args) {
        HashMap<String,Integer> map = new HashMap<>();
        // 添加数据
        map.put("aaa",111);
        map.put("bbb",222);
        map.put("ccc",333);
        // 获取单列集合keySet,然后再获取流
        map.keySet().stream().forEach(s -> System.out.println(s));
            //aaa
            //ccc
            //bbb
        // 获取单列集合entrySet(),然后再获取流
        map.entrySet().stream().forEach(s -> System.out.println(s));
            //aaa=111
            //ccc=333
            //bbb=222
    }

数组获取Stream流

public static void main(String[] args) {
    // 基本数据类型
    int[] arr1 = {1,2,3,4};
    // 引用数据类型
    String[] arr2 = {"a","b","c"};

    // 获取Stream流
    Arrays.stream(arr1).forEach(s -> System.out.println(s));

    Arrays.stream(arr2).forEach(s -> System.out.println(s));
}

零散数据获取Stream流

public static void main(String[] args) {
    // 基本数据类型
    Stream.of(1,2,3,4).forEach(s -> System.out.println(s));
    // 引用数据类型
    Stream.of("aa","bb","cc","dd").forEach(s -> System.out.println(s));
}

注意:Stream接口中静态方法of的细节

方法的形参是一个可变参数,可以传递一堆零散数据,也可传递数组

但是数组必须是引用数据类型,如果是基本数据类型,会把整个数组当作一个元素,放入Stream中

public static void main(String[] args) {
    // 基本数据类型
    int[] arr1 = {1,2,3,4};
    // 引用数据类型
    String[] arr2 = {"a","b","c"};

    Stream.of(arr1).forEach(s -> System.out.println(s));
        // [I@404b9385

    Stream.of(arr2).forEach(s -> System.out.println(s));
        // a
        // b
        // c
}

Stream流的中间方法

image.png

注意1:中间方法,返回新的Stream流,原来的Stream流只能使用一次,推荐使用链式编程

注意2:修改Stream流中的数据,不会影响原来集合或者数组中的数据

filter过滤

static void testFilter(){
    ArrayList<String> list = new ArrayList<>();
    Collections.addAll(list,"白展堂","吕秀才","佟湘玉","郭芙蓉","祝无双","李大嘴","白瓜");
    // filter 过滤
    list.stream().filter(s -> s.startsWith("白")).forEach(s -> System.out.println(s));
}
白展堂
白瓜

limit获取前几个元素

static void testLimit(){
    ArrayList<String> list = new ArrayList<>();
    Collections.addAll(list,"白展堂","吕秀才","佟湘玉","郭芙蓉","祝无双","李大嘴","白瓜");
    // limit获取前3个元素
    list.stream().limit(3).forEach(s -> System.out.println(s));
}
白展堂
吕秀才
佟湘玉

skip跳过前几个元素

static void testSkip(){
    ArrayList<String> list = new ArrayList<>();
    Collections.addAll(list,"白展堂","吕秀才","佟湘玉","郭芙蓉","祝无双","李大嘴","白瓜");
    // skip跳过前3个元素,再取前2个
    list.stream().skip(3).limit(2).forEach(s -> System.out.println(s));
}
郭芙蓉
祝无双

distinct去重

static void testDistinct(){
    ArrayList<String> list = new ArrayList<>();
    Collections.addAll(list,"白展堂","白展堂","白展堂","吕秀才","佟湘玉","郭芙蓉","祝无双","李大嘴","白客");
    // distinct元素去重
    list.stream().distinct().forEach(s -> System.out.println(s));
}
白展堂
吕秀才
佟湘玉
郭芙蓉
祝无双
李大嘴
白客

concat合并Stream流

static void testConcat(){
    ArrayList<String> list1 = new ArrayList<>();
    ArrayList<String> list2 = new ArrayList<>();
    Collections.addAll(list1,"白展堂","祝无双","李大嘴","白客");
    Collections.addAll(list2,"莫言","刘慈欣");
    // concat连接两个stream流
    Stream.concat(list1.stream(),list2.stream()).forEach(s -> System.out.println(s));
}
白展堂
祝无双
李大嘴
白客
莫言
刘慈欣

map转换流中的数据类型

static void testMap(){
    ArrayList<String> list = new ArrayList<>();
    Collections.addAll(list,"白展堂-18","郭芙蓉-19","祝无双-17","李大嘴-20");
    // map转换流中数据
    list.stream().map(s -> Integer.parseInt(s.split("-")[1])).forEach(s -> System.out.println(s));
}
18
19
17
20

Stream流的终结方法

image.png

forEach遍历

count统计

static void testCount(){
    ArrayList<String> list = new ArrayList<>();
    Collections.addAll(list,"白展堂","祝无双","李大嘴","白客");
    System.out.println(list.stream().count());
}

toArray收集流中的数据到数组

toArray()方法的参数作用:创建一个指定类型指定大小的数组

如果调用无参的toArray()方法,将会创建Object类型数组

static void testToArray(){
    ArrayList<String> list = new ArrayList<>();
    Collections.addAll(list,"白展堂","祝无双","李大嘴","白客");
    String[] array = list.stream().toArray(value -> new String[value]);
    System.out.println(Arrays.toString(array));
}
[白展堂, 祝无双, 李大嘴, 白客]

collect收集流中的数据到集合

收集数据到List

static void testCollect1(){
    ArrayList<String> list = new ArrayList<>();
    Collections.addAll(list,"白展堂-男-18","郭芙蓉-女-19","祝无双-女-17","李大嘴-男-20");
    // 收集所有男性
    // 静态方法Collectors.toList()生成一个ArrayList集合
    List<String> list1 = list.stream()
            .filter(s -> "男".equals(s.split("-")[1]))
            .collect(Collectors.toList());
    System.out.println(list1);
}
[白展堂-男-18, 李大嘴-男-20]

收集数据到Set

static void testCollect2(){
    ArrayList<String> list = new ArrayList<>();
    Collections.addAll(list,"白展堂-男-18","郭芙蓉-女-19","祝无双-女-17","李大嘴-男-20");
    // 收集所有男性
    // 静态方法Collectors.toSet()生成一个HashSet
    Set<String> list2 = list.stream()
            .filter(s -> "男".equals(s.split("-")[1]))
            .collect(Collectors.toSet());
    System.out.println(list2);
}

Set中不允许出现重复数据

收集数据到Map

static void testCollect3(){
    ArrayList<String> list = new ArrayList<>();
    Collections.addAll(list,"白展堂-男-18","郭芙蓉-女-19","祝无双-女-17","李大嘴-男-20");
    // 收集所有男性,键为姓名,值为年龄
    // 静态方法Collectors.toMap()生成一个HashMap
    Map<String, Integer> map = list.stream()
            .filter(s -> "男".equals(s.split("-")[1]))
            .collect(Collectors.toMap(
                    s -> s.split("-")[0],
                    s -> Integer.parseInt(s.split("-")[2]))
            );
    System.out.println(map);
}
{白展堂=18, 李大嘴=20}

Map的keyset不允许重复

toMap()中参数一定义生成键的规则,参数二定义生成值的规则