Stream流

发布于:2024-04-18 ⋅ 阅读:(21) ⋅ 点赞:(0)

一.练习(体验Stream流的作用)

需求:

按照下面的要求完成集合的创建和遍历

创建一个集合,存储多个字符元素

(1).把所有以“张”开头的元素存储到新集合中

(2).把“张”开头的,长度为3的元素存储到新集合中

(3).遍历打印最终结果

(没有使用Stream流的效果)

import java.util.ArrayList;

public class Stream {
    public static void main(String[] args) {
        ArrayList<String> list1 = new ArrayList<>();
        list1.add("张无忌");
        list1.add("周芷若");
        list1.add("赵敏");
        list1.add("张强");
        list1.add("张三丰");
        ArrayList<String> list2 = new ArrayList<>();
        for (String string : list1) {
            if (string.startsWith("张")) {
                list2.add(string);
            }
        }
        ArrayList<String> list3 = new ArrayList<>();
        for (String string : list2) {
            if (string.length() == 3) {
                list3.add(string);
            }
        }
        for (String string : list3) {
            System.out.println(string);
        }
    }
}

(使用Stream流之后的效果)

import java.util.ArrayList;

public class Stream {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("张强");
        list.add("张三丰");
        list.stream().filter(name -> name.startsWith("张")).filter(name -> name.length() == 3).forEach(name -> System.out.println(name));
    }
}

二.Stream流

1.思想:

对Stream流按照需求进行过滤操作,之后输出符合要求的数据

2.作用:

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

3.使用步骤

(1).先得到一条Stream流(流水线),并把数据放到这个流水线中

获取方式:

使用单列集合的形式,利用Collection中的默认方法default Stream<E> stream()

import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Consumer;
import java.util.stream.Stream;

public class stream {
    public static void main(String[] args) {
        //单列集合
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "a", "b", "c", "d", "e");
        //获取到一条流水线,并把集合中的所有数据放到流水线上
        Stream<String> stream1 = list.stream();
        //使用终结方法打印流水线上的所有数据
        stream1.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });

        //Lambda表达式
        list.stream().forEach(s -> System.out.println(s));
    }
}

使用双列集合无法直接使用Stream流

import java.util.HashMap;

public class stream {
    public static void main(String[] args) {
        //双列集合(无法直接使用Stream流),使用单列集合进行转换
        HashMap<String, Integer> hm = new HashMap<>();
        hm.put("a", 1);
        hm.put("b", 2);
        hm.put("c", 3);
        hm.put("d", 4);
        //只能获取到键的Stream流
        hm.keySet().stream().forEach(s -> System.out.println(s));
        //直接获取键值对的Stream流
        hm.entrySet().stream().forEach(s -> System.out.println(s));
    }
}

使用数组时,利用Arrays工具类中的静态方法public static<T> Stream<T> stream(T[] array)

import java.util.Arrays;

public class stream {
    public static void main(String[] args) {
        //数组
        int[] arr1 = {1, 2, 3, 4, 5, 6, 7, 8};
        String[] arr2 = {"a", "b", "c"};
        Arrays.stream(arr1).forEach(s -> System.out.println(s));
        Arrays.stream(arr2).forEach(s -> System.out.println(s));
    }
}

在使用一堆零散数据时,使用Stream接口中的静态方法public static<T> Stream<T> of(T...values)

import java.util.stream.Stream;

public class stream {
    public static void main(String[] args) {
        //一堆零散数据
        //基本数据类型
        Stream.of(1, 2, 3, 4, 5).forEach(s -> System.out.println(s));
        //引用数据类型
        Stream.of("a", "b", "c", "d", "e").forEach(s -> System.out.println(s));
    }
}

注意点:最好不要使用将数据存入数组之后再使用Stream.of方法使用Stream流的方式输出数据的方式,如果是存入的基本数据类型,那么输出的就会是整个数组的地址值

(2).使用中间方法对流水线上的数据进行操作

Stream<T> filter(Predicate<? super T>predicate)过滤

import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Predicate;
import java.util.stream.Stream;

public class stream {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张三丰", "张翠山", "张良", "王二", "谢广坤");
        list.stream().filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.startsWith("张");
            }
        }).forEach(s -> System.out.println(s));

        //Lambda表达式(链式编程)
        list.stream().filter(s -> s.startsWith("张")).forEach(s -> System.out.println(s));

        //非链式编程
        Stream<String> stream1 = list.stream().filter(s -> s.startsWith("张"));
        Stream<String> stream2 = stream1.filter(s -> s.length() == 3);
        stream2.forEach(s -> System.out.println(s));
        //虽然非链式编程一直到这里都是能正常编译的,但是到下一步就会因为stream1已经被stream2使用过一次而关闭,因此使用不了
        //Stream<String> stream3=stream1.filter(s->s.length()==3);

        //修改Stream流中的数据不会影响到原本的数据,因此在下方打印list仍然会是一开始输入到list中的完整的数据
        System.out.println(list);
    }
}

Stream<T> limit(long maxSize)获取前几个元素

import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Stream;

public class stream {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张三丰", "张翠山", "张良", "王二", "谢广坤");
        //使用limit方法获取了前三个元素,因此输出的结果是张无忌,周芷若,赵敏
        Stream<String> stream = list.stream().limit(3);
        stream.forEach(s -> System.out.println(s));
    }
}

Stream<T> skip(long n)跳过前几个元素

import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Stream;

public class stream {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张三丰", "张翠山", "张良", "王二", "谢广坤");
        //跳过了前三个元素,因此输出的结果为张三丰,张翠山,张良,王二,谢广坤
        Stream<String> stream = list.stream().skip(3);
        stream.forEach(s -> System.out.println(s));
    }
}

Stream<T> distinct()元素去重,依赖(hashCode和equals方法)

import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Stream;

public class stream {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "张无忌", "张无忌", "周芷若", "赵敏", "张三丰", "张翠山", "张良", "王二", "谢广坤");
        //去除了重复的张无忌元素,因此输出的结果中会少一个张无忌
        Stream<String> stream = list.stream().distinct();
        stream.forEach(s -> System.out.println(s));
    }
}

static<T> Stream<T> concat(Stream a,Stream b)合并a和b两个Stream流为一个

import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Stream;

public class stream {
    public static void main(String[] args) {
        ArrayList<String> list1 = new ArrayList<>();
        ArrayList<String> list2 = new ArrayList<>();
        Collections.addAll(list1, "张无忌", "张无忌", "周芷若");
        Collections.addAll(list2, "赵敏", "张三丰", "张翠山", "张良", "王二", "谢广坤");
        Stream<String> stream1 = list1.stream();
        Stream<String> stream2 = list2.stream();
        //通过concat方法将两个Stream流进行了合并,最后输出的数据是stream1和stream2中所存储的全部的数据
        Stream<String> stream3 = Stream.concat(stream1, stream2);
        stream3.forEach(s -> System.out.println(s));
    }
}

Stream<R> map(Function<T, R> mapper)转换流中的数据类型 

import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Function;

public class stream {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "张无忌-1", "周芷若-2", "赵敏-3", "张三丰-4", "张翠山-5", "张良-6", "王二-7", "谢广坤-8");
        //需求:只获取里面的数字数据并进行打印
        list.stream().map(new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                String[] arr = s.split("-");
                String numberString = arr[1];
                int number = Integer.parseInt(numberString);
                return number;
            }
        }).forEach(s -> System.out.println(s));

        //Lambda表达式
        list.stream().map(s -> Integer.parseInt(s.split("-")[1])).forEach(s -> System.out.println(s));
    }
}

注意点1:中间方法,返回新的Stream流,原来的Stream流只能使用一次,所以建议使用链式编程

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

(3).使用终结方法对流水线上的数据进行操作

终结方法:

void forEach(Consumer action)遍历

import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Consumer;

public class stream {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张三丰", "张翠山", "张良", "王二", "谢广坤");
        list.stream().forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });

        //Lambda表达式
        list.stream().forEach(s -> System.out.println(s));
    }
}

long count()统计

import java.util.ArrayList;
import java.util.Collections;

public class stream {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张三丰", "张翠山", "张良", "王二", "谢广坤");
        //使用count方法对list中的元素进行计数,最终得出的结果为8
        long count = list.stream().count();
        System.out.println(count);
    }
}

toArray()收集流中的数据,放到数组中

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.function.IntFunction;

public class stream {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张三丰", "张翠山", "张良", "王二", "谢广坤");
        //空参构造的toArray方法
        Object[] array = list.stream().toArray();
        System.out.println(Arrays.toString(array));
        //带有参数的toArray方法
        //InFunction的泛型:具体类型的数组
        //apply的形参:流中数据的个数
        //apply的返回值:具体类型的数组
        String[] array1 = list.stream().toArray(new IntFunction<String[]>() {
            @Override
            public String[] apply(int value) {
                return new String[value];
            }
        });
        System.out.println(Arrays.toString(array1));
        
        //Lambda表达式
        String[] array2=list.stream().toArray(value -> new String[value]);
        System.out.println(Arrays.toString(array2));
    }
}

collect(Collector collector)收集流中的数据,放到集合中

有关collect方法的详解请看:

https://blog.csdn.net/NaZiMeKiY/article/details/137685709

三.总结

1.Stream流的作用

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

2.Stream的使用步骤

(1).获取Stream流对象

(2).使用中间方法处理数据

(3).使用终结方法处理数据

3.如何获取Stream流对象

(1).单列集合:Collection中的默认方法stream

(2).双列集合:不能直接获取

(3).数组:Arrays工具类型中的静态方法stream

(4).一堆零散的数据:Stream接口中的静态方法of

4.常见方法

中间方法:filter,limit,skip,distinct,concat,map

终结方法:forEach,count,collect