Java 8系列之StreamApi

Stream的三个操作步骤

1.创建Stream
2.中间操作
3.终止操作

1.创建Stream

    @Test
    public void creatStream(){
        //1.通过Collection系列集合提供的stream()或者parallelStream();
        List<String> list=new ArrayList<String>();
        Stream<String> stream1 = list.stream();
        //2.通过Arrays中的静态方法Stream()获取数组流
        Integer[] ints=new Integer[10];
        Stream<Integer> stream2 = Arrays.stream(ints);
        //3.通过Stream类中的静态方法of()
        Stream<String> stream3 = Stream.of("aa", "bb", "cc");
        Stream<Object> empty = Stream.empty();
        //4.创建无限流
        //迭代
        Stream<Integer> stream4 = Stream.iterate(0, x -> x + 2);
        //生成
        Stream<Double> stream5 = Stream.generate(() -> Math.random());
    }

2.中间操作

创建一个Student类用来做测试

public class Student {
   private String name;
   private int age;
   private int score;
   ...
   private Status status;
   public enum Status{
       Free,Busy,Vocation
   }
}
   List<Student> students=Arrays.asList(
           new Student("mm",22,78,Student.Status.Busy),
           new Student("kk",23,98,Student.Status.Free),
           new Student("qq",21,56,Student.Status.Vocation),
           new Student("hh",23,43,Student.Status.Busy),
           new Student("hh",23,43,Student.Status.Busy)
   );

中间操作–筛选和切片

   /**
    * 中间操作--筛选和切片
    */
   @Test
   public void middle_(){
       //filer:过滤  Stream<T> filter(Predicate<? super T> predicate);
       System.out.println("-------------------------------------------");
       Stream<Student> filer = students.stream().filter(s -> s.getScore() > 60);
       filer.forEach(System.out::println);
       //limit:截断
       System.out.println("-------------------------------------------");
       Stream<Student> limit = students.stream().limit(2);
       limit.forEach(System.out::println);
       //skip:跳过
       System.out.println("-------------------------------------------");
       Stream<Student> skip = students.stream().skip(2);
       skip.forEach(System.out::println);
       //distinct:去重,通过流所生成元素的hashCode()和equals()去除重复的元素(也就是说Student要重写hashCode()和equals())
       System.out.println("-------------------------------------------");
       Stream<Student> distinct = students.stream().distinct();
       distinct.forEach(System.out::println);
       //peek:查看Stream流水线中的数据流的值
       System.out.println("-------------------------------------------");
       Stream<Integer> peek = students.stream().map(o->o.getScore()).peek(o-> System.out.print("原分数:"+o)).map(o->o+20);
       peek.forEach(o-> System.out.println(",新分数:"+o));
   }

中间操作–映射

    /**
     * 中间操作--映射
     */
    @Test
    public void middle_map(){
        //map:映射,参数为Function<? super T, ? extends R> mapper
        System.out.println("-------------------------------------------");
        Stream<String>  map= students.stream().map(Student::getName);
        map.forEach(System.out::println);
        //flatmap:映射,参数为Function<? super T, ? extends Stream<? extends R>> mapper,将Function方法返回的每个流中的每个元素放到流中
        //map与flatmap的区别像是list的add()与addAll(),当然也不完全类似
        System.out.println("-------------------------------------------");
        Stream<Character> flatMap = students.stream().flatMap(s -> toBeCharacter(s.getName()));
        flatMap.forEach(System.out::print);
        //进一步学习map和flatmap
        String[] arrayOfWords = {"Goodbye", "World"};
        Stream<String> words = Arrays.stream(arrayOfWords);
        //map(Arrays::stream)得到的是一个流的列表
        List<Stream<String>> map1 = words.map(word -> word.split(""))
                .map(Arrays::stream)
                .distinct()
                .collect(toList());
        System.out.println("---------------------------------------map1:"+map1.get(0).collect(toList())+","+map1.get(1).collect(toList()));
        //流只能消费一次,所以words已经被消费了,需要重复创建
        Stream<String> words1 = Arrays.stream(arrayOfWords);
        //各个数组并不是分别映射成一个流,而是映射成流的内容
        List<String> flatMap1 = words1.map(word -> word.split(""))
                .flatMap(Arrays::stream)
                .distinct()
                .collect(toList());
        System.out.println("---------------------------------------flatMap1:"+flatMap1);

    }
    public static Stream<Character> toBeCharacter(String str){
        List<Character> list=new ArrayList<>();
        for (Character c:str.toCharArray()){
            list.add(c);
        }
        return list.stream();
    }

中间操作–排序

   /**
    * 中间操作--排序
    */
   @Test
   public void middle_sort(){
       //sorted():排序,数组中的对象需要实现Comparable
       //sorted(Comparator<? super T> comparator):排序,通过Comparator定制排序
       Stream<Student> sorted = students.stream().sorted((x, y) -> Integer.compare(x.getAge(), y.getAge()));
       sorted.forEach(System.out ::println);
   }

2.终止操作

终止操作–查找与匹配

   /**
    * 终止操作--查找与匹配
    */
   @Test
   public void end_match_find(){
       //allMatch:检查是否匹配所有元素
       boolean allMatch = students.stream().allMatch(s -> s.getStatus().equals(Student.Status.Busy));
       System.out.println("是否所有人都很忙:"+allMatch);
       //anyMatch:检查是否匹配一个元素
       boolean anyMatch = students.stream().anyMatch(s -> s.getStatus().equals(Student.Status.Busy));
       System.out.println("是否有人很忙:"+anyMatch);
       //noneMatch:检查是否没有匹配所有元素
       boolean noneMatch = students.stream().noneMatch(s -> s.getStatus().equals(Student.Status.Busy));
       System.out.println("是否所有人都很闲:"+noneMatch);
       //findFirst:返回第一个元素
       Optional<Student> first = students.stream().findFirst();
       System.out.println("第一个元素:"+first.get());
       //findAny:返回当前流中的任意元素
       Optional<Student> any = students.parallelStream().filter(s -> s.getStatus().equals(Student.Status.Busy)).findAny();
       System.out.println("任一个元素:"+any.get());
   }

终止操作–统计

   /**
    * 终止操作--统计
    */
   @Test
   public void end_Statistics(){
       //count:返回流中元素的总个数
       long count = students.stream().count();
       System.out.println("学生人数:"+count);
       //max:返回流中最大值
       Optional<Student> max = students.stream().max((x, y) -> Integer.compare(x.getScore(), y.getScore()));
       System.out.println("分数最高的学生:"+max.get());
       //min:返回流中最小值
       Optional<Integer> min = students.stream().map(Student::getScore).min(Integer::compare);
       System.out.println("最低分数"+min.get());
       //sum(),实际是没有这个方法的,因为无法对stream<T>中的T可能并不是数值,无法对它做控制,解决方式如下
       //引入数值流,注意mapToInt()返回的对象是IntStream,不是stream<T>
       IntStream intStream = students.stream().mapToInt(Student::getScore);
       System.out.println("总分数"+intStream.sum());
       //将IntStream转为stream<T>,使用boxed()方法
       // Stream<Integer> stream = intStream.boxed();


   }

终止操作–归约

   /**
    * 终止操作--归约
    */
   @Test
   public void end_reduce(){
       //reduce:归约,元素计算
       //第一种,有初始值:T reduce(T identity, BinaryOperator<T> accumulator);
       Integer reduce = students.stream().map(s -> s.getScore()).reduce(0, (x, y) -> x + y);
       System.out.println("分数总和:"+reduce);
       //第二种,无初始值:Optional<T> reduce(BinaryOperator<T> accumulator);可能为空,所以返回Optional
       Optional<Integer> reduce1 = students.stream().map(s -> s.getScore()).reduce((x, y) -> x + y);
       System.out.println("分数总和:"+reduce1.get());
       Stream<Integer> stream = Arrays.stream(new Integer[2]);
       //Optional<Integer> reduce2 = stream.reduce((x, y) -> x + y);
       //System.out.println("结果是否为空:"+reduce2.isPresent());
       //求最大值,最小值
       Optional<Integer> maxOptional = students.stream().map(s -> s.getScore()).reduce(Integer::max);
       System.out.println("最大值 :"+maxOptional.get());

   }

终止操作–收集

   /**
    * 终止操作--收集
    */
   @Test
   public void end_collect(){
       //collection:收集,给stream中的元素做汇总,参数Collector<? super T, A, R> collector
       System.out.println("----------------------------list------------------------------");
       List<String> list = students.stream().map(s -> s.getName()).collect(toList());
       list.forEach(System.out::println);
       System.out.println("-------------------------set---------------------------------");
       Set<String> set = students.stream().map(s -> s.getName()).collect(Collectors.toSet());
       set.forEach(System.out::println);
       System.out.println("------------------------hashSet----------------------------------");
       HashSet<String> hashSet = students.stream().map(s -> s.getName()).collect(Collectors.toCollection(HashSet::new));
       hashSet.forEach(System.out::println);
       System.out.println("------------------------map----------------------------------");
       Map<String, Student> map = students.stream().collect(Collectors.toMap(Student::getName, e -> e,(e1,e2)->e1));
       for(String s:map.keySet()){
           System.out.println(map.get(s));
       }

   }

终止操作–收集–groupingBy

   /**
    * 终止操作--收集--groupingBy
    */
   @Test
   public void end_collectors_groupingBy(){
       //分组
       System.out.println("---------------------原始写法-------group by------------------------------");
       Map<Student.Status, List<Student>> group1=new HashMap<Student.Status, List<Student>>();
       for(Student s: students){
           Student.Status status = s.getStatus();
           List<Student> students = group1.get(status);
           if(students==null){
               students=new ArrayList<Student>();
               group1.put(s.getStatus(),students);
           }
           students.add(s);
       }
       for (Student.Status s:group1.keySet()){
           System.out.println(s+":"+group1.get(s));
       }
       System.out.println("------------------------java8----group by------------------------------");
       Map<Student.Status, List<Student>> group = students.stream().collect(Collectors.groupingBy(Student::getStatus));
       for (Student.Status s:group.keySet()){
           System.out.println(s+":"+group.get(s));
       }
       //groupingBy(f)是groupingBy(f,toList())的缩写
       Map<String, List<Student>> groupBy = students.stream().collect(Collectors.groupingBy(o -> {
           if (o.getScore() < 60) return "不及格";
           else if (o.getScore() < 80) return "良";
           else return "优秀";
       }));
       for (String s:groupBy.keySet()){
           System.out.println(s+":"+groupBy.get(s));
       }
       System.out.println("------------------------java8----多级分组group by------------------------------");
       Map<Student.Status, Map<String, List<Student>>> groupBys = students.stream().collect(Collectors.groupingBy(Student::getStatus, Collectors.groupingBy(o -> {
           if (o.getScore() < 60) return "不及格";
           else if (o.getScore() < 80) return "良";
           else return "优秀";
       })));
       for (Student.Status s:groupBys.keySet()){
           System.out.println(s+":"+groupBys.get(s));
       }
       //与 groupingBy 联合使用的其他收集器
       System.out.println("--------------collectingAndThen,求每个状态中分数最高的学生-----------------------------");
       Map<Student.Status, Student> studentMap = students.stream().collect(Collectors.groupingBy(Student::getStatus, Collectors.collectingAndThen(
               Collectors.maxBy(Comparator.comparing(Student::getScore)), Optional::get)));
       for (Student.Status s:studentMap.keySet()){
           System.out.println(s+":"+studentMap.get(s));
       }
       System.out.println("--------------averagingInt,求每个状态的平均分-----------------------------");
       Map<Student.Status, Double> statusDoubleMap = students.stream().collect(Collectors.groupingBy(Student::getStatus, Collectors.averagingInt(Student::getScore)));
       for (Student.Status s:statusDoubleMap.keySet()){
           System.out.println(s+":"+statusDoubleMap.get(s));
       }
       System.out.println("--------------averagingInt,求每个状态的学生集合-----------------------------");
       Map<Student.Status, Set<String>> statusSetMap = students.stream().collect(Collectors.groupingBy(Student::getStatus, Collectors.mapping(Student::getName, Collectors.toSet())));
       for (Student.Status s:statusSetMap.keySet()){
           System.out.println(s+":"+statusSetMap.get(s));
       }
   }

终止操作–分区–partitioningBy

   /**
    * 终止操作--分区--partitioningBy
    */
   @Test
   public void end_collectors_partitioningBy(){
       //参数是Predicate
       Map<Boolean, List<Student>> map = students.stream().collect(Collectors.partitioningBy(o -> o.getScore() > 90));
       System.out.println("成绩大于90分的学生:"+map.get(true));
       //简单的分区也可以用filter来实现,但分区可以实现多级分区
       Map<Boolean, Set<String>> map1 = students.stream().collect(Collectors.partitioningBy(o -> o.getScore() > 90, Collectors.mapping(Student::getName, Collectors.toSet())));
       System.out.println("成绩大于90分的学生:"+map1.get(true));

   }

终止操作–收集器–reducing: 汇总归约


   /**
    * 终止操作--收集器--reducing: 汇总归约
    */
   @Test
   public void end_collectors_reducing(){
       //个数,底层:reducing(0L, e -> 1L, Long::sum)
       Long count = students.stream().collect(Collectors.counting());
       System.out.println("一共有多少个分数:"+count);
       //最高分
       Optional<Student> maxScore = students.stream().collect(Collectors.maxBy(Comparator.comparing(Student::getScore)));
       System.out.println("最高分:"+maxScore);
       //平均值
       Double average = students.stream().collect(Collectors.averagingInt(s -> s.getScore()));
       System.out.println("平均分:"+average);
       //总和
       Integer sum = students.stream().collect(Collectors.summingInt(s -> s.getScore()));
       System.out.println("总分:"+sum);
       //统计信息
       IntSummaryStatistics statistics = students.stream().collect(Collectors.summarizingInt(Student::getScore));
       System.out.println("统计信息:"+statistics);
       //连接字符串
       String studentNames = students.stream().map(Student::getName).collect(Collectors.joining(","));
       System.out.println("学生:"+studentNames);
       //广义归约reducing
       Integer sumScore = students.stream().collect(Collectors.reducing(0, Student::getScore, Integer::sum));
       System.out.println("总分:"+sumScore);
       Optional<Integer> sumScore1 = students.stream().map(Student::getScore).collect(Collectors.reducing(Integer::sum));
       System.out.println("总分:"+sumScore1.get());

   }


猜你喜欢

转载自blog.csdn.net/qq_39172525/article/details/84716326