Stream流

作者: 下雨之後 | 来源:发表于2022-01-24 11:35 被阅读0次
    获取stream流的两种方式

    1、根据Collection获取
    2、Stream中静态方法of获取
    基本数据类型数组不可以获取stream

    stream常用方法,有终结方法不再调用,非终结方法可以继续调用

    终结方法:forEach、count
    非终结方法:filter、limit、skip、map、sorted、distinct、match、find、max、reduce、mapToInt、concat

    注意事项
    1、stream流只能操作一次
    2、stream方法返回的是新流
    3、stream不调用终结方法,终结的操作不会执行

    List<String> list = new ArrayList<>();
    Collections.addAll(list, "迪丽热巴", "宋远桥", "苏星河", "老子", "庄子", "孙子");
    
    forEach
    list.stream().forEach((String str) -> {
        System.out.println(str);
    });
    list.stream().forEach(str -> System.out.println(str));
    list.stream().forEach(System.out::println);
    
    count
    long count = list.stream().count();
    System.out.println("count = " + count);
    
    filter

    得到名字长度为3个字的人(过滤)

    list.stream().filter((String s) -> {
        return s.length() == 3;
    }).forEach(System.out::println);
    list.stream().filter(s -> s.length() == 3).forEach(System.out::println);
    
    limit

    获取前三个数据

    list.stream().limit(3).forEach(System.out:println);
    
    skip

    跳过前2个数据

    list.stream().skip(2).forEach(System.out::println);
    
    map

    Stream流中的字符串转换为Integer
    map可以将一种类型的流转换为另一种类型的流

    Stream<String> original = Stream.of("11", "22", "33");
    Stream<Integer> stream = original.map((String s) -> {
        return Integer.parseInt(s);
    });
    original.map(s -> Integer.parseInt(s)).forEach(System.out::println);
    original.map(Integer::parseInt).forEach(System.out::println);
    
    sorted

    将数据排序
    无参按照默认排序,有参自定义排序

    Stream<Integer> stream = Stream.of(33, 22, 11, 55);
    stream.sorted().forEach(System.out::println);
    stream.sorted((Integer i1, Integer i2) -> {
        return i2 - i1;
    }).forEach(System.out::println);
    stream.sorted((i1, i2) -> i2 - i1).forEach(System.out::println);
    
    distinct

    对数字去重

    Stream<Integer> stream = Stream.of(22, 33, 22, 11, 33);
    stream.distinct().forEach(System.out::println);
    

    对字符串去重

    Stream<String> stream = Stream.of("aa", "bb", "aa", "bb", "cc");
    stream.distinct().forEach(System.out::println);
    

    对自定义对象去重
    person类中重写equalshashCode方法就可以去重了

    Stream<Person> personStream = Stream.of(
            new Person("貂蝉", 18), 
            new Person("杨玉环", 20), 
            new Person("杨玉环", 20), 
            new Person("西施", 16), 
            new Person("西施", 16), 
            new Person("王昭君", 25));
    personStream.distinct().forEach(System.out::println);
    
    match

    allMatch匹配所有元素,所有都需要满足条件

    Stream<Integer> stream = Stream.of(5, 3, 6, 1);
    boolean b = stream.allMatch((Integer i) -> {
        return i > 5;
    });
    boolean b1 = stream.allMatch(i -> i > 5);
    System.out.println(b); // false
    

    anyMatch匹配某个元素,只要有一个满足条件即可

    boolean b2 = stream.anyMatch(i -> i > 5);
    System.out.println(b2); // true
    

    noneMatch匹配所有元素,所有都不满足条件

    boolean b3 = stream.noneMatch(i -> i < 5);
    System.out.println(b3); // false
    
    find
    Stream<Integer> stream = Stream.of(33, 11, 22, 5);
    Optional<Integer> first = stream.findFirst();
    System.out.println(first.get());
    Optional<Integer> any = stream.findAny();
    System.out.println(any.get());
    
    max
    Stream<Integer> stream = Stream.of(5, 3, 6, 1);
    // 1 3 5 6
    Optional<Integer> max = stream.max((o1, o2) -> o1 - o2);
    System.out.println(max.get()); // 取出最后一个
    
    min
    Stream<Integer> stream = Stream.of(5, 3, 6, 1);
    // 1 3 5 6
    Optional<Integer> min = stream.min((o1, o2) -> o1 - o2);
    System.out.println(min.get()); // 取出第一个
    
    reduce

    将数据归纳得到一个数据

    // 将数据归纳得到一个数据
    Stream<Integer> stream = Stream.of(4, 5, 3, 9);
    // 第一个参数identity:默认值
    // 第二个参数accumulator:对数据进行处理的方式
    // reduce如何执行
    // 第一次,将默认值赋值给x,取出集合第一个元素赋值给y
    // 第二次,将上一次返回的结果赋值x,取出集合第二个元素赋值给y
    // 第三次,将上一次返回的结果赋值x,取出集合第三个元素赋值给y
    // 第四次,将上一次返回的结果赋值x,取出集合第四个元素赋值给y
    int reduce = stream.reduce(0, (x, y) -> {
        System.out.println("x = " + x + ", y = " + y);
        return x + y;
    });
    System.out.println(reduce); // 21
    // 获取最大值
    Integer max = stream.reduce(0, (x, y) -> {
        return x > y ? x : y;
    });
    System.out.println(max); // 9
    
    map和reduce组合
    // 求出所有年龄的总和
    Stream<Person> stream = Stream.of(
            new Person("刘德华", 58),
            new Person("张学友", 56),
            new Person("郭富城", 54),
            new Person("黎明", 52)
    );
    // 得到所有年龄,然后求和
    Integer totalAge = stream.map(p -> p.getAge()).reduce(0, (x, y) -> x + y);
    System.out.println(totalAge);
    Integer totalAge1 = stream.map(p -> p.getAge()).reduce(0, Integer::sum);
    // 找出最大年龄
    Integer maxAge = stream.map(p -> p.getAge()).reduce(0, (x, y) -> x > y ? x : y);
    System.out.println(maxAge);
    Integer maxAge1 = stream.map(p -> p.getAge()).reduce(0, Math::max);
    // 统计a出现的次数
    Stream<String> stream1 = Stream.of("a", "c", "b", "a", "b", "a");
    Integer count = stream1.map(s -> {
        if (s == "a") {
            return 1;
        } else {
            return 0;
        }
    }).reduce(0, Integer::sum);
    System.out.println(count);
    
    mapToInt

    Integer占用内存比int多,在Stream流中要进行装箱拆箱耗性能

    Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
    // 把大于3的打印出来
    stream.filter(n -> n > 3).forEach(System.out::println);
    // IntStream:内部操作的是int类型的数据,可以节省内存,减少自定装箱拆箱
    IntStream intStream = stream.mapToInt((Integer n) -> {
        return n.intValue();
    });
    IntStream intStream = stream.mapToInt(Integer::intValue);
    intStream.filter(n -> n > 3).forEach(System.out::println);
    
    concat

    将两个流合并成一个流,使用静态方法concat

    Stream<String> streamA = Stream.of(“张三”);
    Stream<String> streamB = Stream.of(“李四”);
    Stream<String> newStream = Stream.concat(streamA, streamB);
    // 合并后不能在操作之前的流
    // 只支持将两个流合成一个
    newStream.forEach(System.out::println);
    
    综合案例
    //第一个队伍
    List<String) one = List. of("迪丽热巴", "宋远桥", "苏星河", "老子", "庄子", "孙子", "洪七公");
    //第二个队伍
    List<String) two =List. of("古力娜扎", "张无忌", "张三丰", "赵丽颖", "张二狗", "张天爱", "张三");
    //1.第一个队伍只要名字为3个字的成员姓名;
    //2.第一个队伍筛选之后只要前3个人;
    Stream<String> streamA = one.stream().filter(s -> s.length() == 3).limit(3).forEach(System::println);
    //3.第二个队伍只要姓张的成员姓名;
    //4.第二个队伍筛选之后不要前2个人;
    Stream<String> streamB = two.stream().filter(s -> s.startsWith(“张”)).skip(2).forEach(System::println);
    //5.将两个队伍合并为一个队伍;
    Stream<String> streamAB = Stream.concat(streamA, streamB);
    //6.根据姓名创建Person对象;
    //7.打印整个队伍的Person对象信息。
    streamAB.map(Person::new).forEach(System::println);
    

    收集Stream流中的结果

    收集到集合中

    Stream<String> stream = Stream.of("aa", "bb", "cc");
    List<String> list = stream.collect(Collectors.toList());
    System.out.println(list);
    Set<String> set = stream.collect(Collectors.toSet());
    System.out.println(set);
    // 收集到指定集合中ArrayList
    ArrayList<String> arrayList = stream.collect(Collectors.toCollection(ArrayList::new));
    System.out.println(arrayList);
    // 收集到指定集合中HashSet
    HashSet<String> hashSet = stream.collect(Collectors.toCollection(HashSet::new));
    System.out.println(hashSet);
    

    收集到数组中

    Object[] objs = stream.toArray();
    String[] strs = stream.toArray(String[]::new);
    
    对流数据进行聚合计算
    Stream<Student> studentStream = Stream.of(
        new Student ( name: "赵丽颖", age: 58, socre: 95), 
        new Student ( name: "杨颖", age: 56, socre: 88)
        new Student ( name: "迪丽热巴", age: 56, socre: 99),
        new Student ( name: "柳岩", age: 52, socre: 77));
    // 获取最大值
    Optional<Studeng> max = studentStream.collect(Collectors.maxBy(s1, s2) -> s1.getSocre() - s2.getSocre);
    System.out.println(max.get());
    // 获取最小值
    Optional<Studeng> min = studentStream.collect(Collectors.minBy(s1, s2) -> s1.getSocre() - s2.getSocre);
    System.out.println(min.get());
    // 求总和
    Integer sum = studentStream.collect(Collectors.summingInt(s -> s.getAge()));
    System.out.println(sum);
    // 求平均值
    Double avg = studentStream.collect(Collectors.averagingInt(s -> s.getSocre()));
    System.out.println(avg);
    Double avg = studentStream.collect(Collectors.averagingInt(Student::getSocre));
    // 统计数量
    Long count = studentStream.collect(Collectors.counting()));
    System.out.println(count);
    
    对流数据进行分组
    // 对流数据进行分组
    Stream<Student> studentStream = Stream.of(
            new Student ( "赵丽颖", 52, 95),
            new Student ( "杨颖", 56, 88),
            new Student ( "迪丽热巴", 56, 55),
            new Student ( "柳岩", 52, 33));
    Map<Integer, List<Student>> map =  studentStream.collect(Collectors.groupingBy((s) -> s.getAge()));
    map.forEach((k, v) -> {
        System.out.println(k + "::" + v);
    });
    Map<Integer, List<Student>> map =  studentStream.collect(Collectors.groupingBy(Student::getAge));
    // 将分数大于60的分一组,小于60的分一组
    Map<String, List<Student>> map =  studentStream.collect(Collectors.groupingBy((s) -> {
        if (s.getScore() > 60) {
            return "及格";
        } else {
            return "不及格";
        }
    }));
    map.forEach((k, v) -> {
        System.out.println(k + "::" + v);
    });
    
    对流数据进行多级分组
    Map<Integer, Map<String, List<Student>>> map = studentStream.collect(Collectors.groupingBy(Student::getAge, Collectors.groupingBy(s -> {
        if (s.getScore() > 60) {
            return "及格";
        } else {
            return "不及格";
        }
    })));
    map.forEach((k, v) -> {
        System.out.println(k);
        v.forEach((k2, v2) -> {
            System.out.println("\t" + k2 + " == " + v2);
        });
    });
    
    对流数据进行分区
    Map<Boolean, List<Student>> map = studentStream.collect(Collectors.partitioningBy(s -> s.getScore() > 60));
    map.forEach((k, v) -> {
        System.out.println(k + "::" + v);
    });
    
    对流数据进行拼接
    // 根据一个字符拼接
    String names = studentStream.map(Student::getName).collect(Collectors.joining("_"));
    System.out.println(names);
    // 根据三个字符拼接
    String names = studentStream.map(Student::getName).collect(Collectors.joining("_", "^_^", "v_v"));
    System.out.println(names);
    

    并行Stream流

    获取并行Stream流的两种方式
    1 直接获取并行的Stream

    list.parallelStream();
    

    2 将串行流转成并行流

    list.stream().parallel();
    Stream.of(4, 5, 3, 9, 1, 2, 6).parallel().filter(
            s -> {
                System.out.println(Thread.currentThread() + "::" + s);
                return s > 3;
            }).count();
    
    for、串行、并行效率对比

    并行 > for > 串行

    parallelStream线程安全问题
    List<Integer> list = new ArrayList<>();
    IntStream.rangeClosed(1, 1000).parallel().forEach(i -> {
        list.add(i);
    });
    System.out.println(list.size());
    // 解决线程安全问题方案一:使用同步代码块
    Object obj = new Object();
    List<Integer> list = new ArrayList<>();
    IntStream.rangeClosed(1, 1000).parallel().forEach(i -> {
        synchronized(obj) {
            list.add(i);
        }
    });
    System.out.println(list.size());
    // 解决线程安全问题方案二:使用线程安全集合
    //Vector<Integer> vectorList = new Vector <>();
    List<Integer> list = new ArrayList<>();
    List<Integer> synchronizedList = Collections.synchronizedList(list);
    IntStream.rangeClosed(1, 1000).parallel().forEach(i -> {
        //vectorList.add(i);
        synchronizedList.add(i);
    });
    System.out.println(list.size());
    // 解决线程安全问题方案三:调用Stream流的collect和toArray方法
    List<Integer> list = IntStream.rangeClosed(1, 1000).parallel().boxed().collect(Collectors.toList());
    System.out.println(list.size());
    

    相关文章

      网友评论

          本文标题:Stream流

          本文链接:https://www.haomeiwen.com/subject/yuixqrtx.html