zoukankan      html  css  js  c++  java
  • Java8之stream

    项目上对于list集合操作使用stream流较多,因此专门抽了个时间整理下

    整理思路来源于这边博客,讲解的很清晰[传送门](https://blog.csdn.net/y_k_y/article/details/84633001 "传送门")

    这篇博客则侧重于实现方法的展示,主要涉及的中间操作符和终止操作符如下

    需要注意的是,stream转换流并不会改动原始对象

    (1)中间操作符

    filter 过滤操作,把不想要的数据过滤。
    sorted(unordered) 排序操作,对元素排序,前提是实现Comparable接口,当然也可以自定义比较器。

    (2)终止操作符

    collect 收集操作,将所有数据收集起来,这个操作非常重要,官方的提供的Collectors 提供了非常多收集器,可以说Stream 的核心在于Collectors。
    count 统计操作,统计最终的数据个数。
    findFirst、findAny 查找操作,查找第一个、查找任何一个 返回的类型为Optional。

    完整代码如下

      1 public class PorblemSolution {
      2     
      3     public static void main(String[] args){
      4         List<Student> list = new ArrayList<Student>();
      5         list.add(new Student(18,180,'男',"张三"));
      6         list.add(new Student(19,170,'女',"李四"));
      7         list.add(new Student(19,170,'男',"王五"));
      8         list.add(new Student(20,180,'女',"赵六"));
      9         list.add(new Student(20,181,'男',"陈七"));
     10         
     11         // stream接口中定义为  Stream<T> filter(Predicate<? super T> predicate);
     12         // filter内部参数需为断言语句
     13         List<Student> res1 = list.stream().filter(stu->stu.getSex()=='男').collect(Collectors.toList());
     14         System.out.println(res1.toString());//  [姓名:张三年龄:18身高:180性别:男, 姓名:王五年龄:19身高:170性别:男, 姓名:陈七年龄:20身高:181性别:男]
     15         
     16         Predicate<Student> stuFilter = (stu->stu.getSex()=='女');
     17         List<Student> res2 = list.stream().filter(stuFilter).collect(Collectors.toList());
     18         System.out.println(res2.toString());// [姓名:李四年龄:19身高:170性别:女, 姓名:赵六年龄:20身高:180性别:女]
     19         
     20         
     21         //  Optional的教程可以看菜鸟教程的这边速通讲解https://www.runoob.com/java/java8-optional-class.html
     22         Optional<Student> firstA = res1.stream().filter(stu->stu.getHeight()==180).findFirst();
     23         System.out.println(firstA.get());// 姓名:张三年龄:18身高:180性别:男
     24         
     25         Optional<Student> firstAny = res2.stream().filter(stu->stu.getSex()=='女').findAny();
     26         System.out.println(firstAny.isPresent() ? firstAny.get():"对象为空");// 姓名:李四年龄:19身高:170性别:女
     27         
     28         int femaleCount = (int) list.stream().filter(stuFilter).count();
     29         System.out.println("femaleCount="+femaleCount);// femaleCount=2
     30         
     31         // 
     32         // 多字段排序,需实现comparator接口
     33         list = list.stream().sorted(
     34                 (stu1, stu2) -> {
     35                     if (stu1.getAge()==stu2.getAge()) {
     36                         return stu2.getHeight()-stu1.getHeight();
     37                     } else {
     38                         return stu1.getAge()-stu2.getAge();
     39                     }
     40                 }).collect(Collectors.toList());
     41         System.out.println(list.toString());
     42         // [姓名:张三年龄:18身高:180性别:男, 姓名:李四年龄:19身高:170性别:女, 姓名:王五年龄:19身高:170性别:男, 姓名:陈七年龄:20身高:181性别:男, 姓名:赵六年龄:20身高:180性别:女]
     43         
     44         // 个性化类通过实现Comparable接口自定义排序规则
     45         list = list.stream().sorted().collect(Collectors.toList());
     46         System.out.println(list.toString());
     47         // [姓名:张三年龄:18身高:180性别:男, 姓名:李四年龄:19身高:170性别:女, 姓名:王五年龄:19身高:170性别:男, 姓名:赵六年龄:20身高:180性别:女, 姓名:陈七年龄:20身高:181性别:男]
     48         
     49         // 通过lambda表达式定义排序规则(这里以身高为例)
     50         list = list.stream().sorted((stu1,stu2)->(stu1.getHeight()-stu2.getHeight())).collect(Collectors.toList());
     51         System.out.println(list.toString());
     52         // [姓名:李四年龄:19身高:170性别:女, 姓名:王五年龄:19身高:170性别:男, 姓名:张三年龄:18身高:180性别:男, 姓名:赵六年龄:20身高:180性别:女, 姓名:陈七年龄:20身高:181性别:男]
     53         
     54         // 利用function实现比较器,进而实现多字段比较
     55         Function<Student, Integer> byAge = (Student) -> Student.getAge();
     56         Function<Student, Integer> byHeight = (Student) -> Student.getHeight();
     57         Comparator<Student> mySort = Comparator.comparing(byAge).thenComparing(byHeight);
     58         list = list.stream().sorted(mySort).collect(Collectors.toList());
     59         System.out.println(list.toString());
     60         // [姓名:张三年龄:18身高:180性别:男, 姓名:李四年龄:19身高:170性别:女, 姓名:王五年龄:19身高:170性别:男, 姓名:赵六年龄:20身高:180性别:女, 姓名:陈七年龄:20身高:181性别:男]
     61          
     62         Map<Integer, List<Student>> ageMap = list.stream().collect(Collectors.groupingBy(Student::getAge));
     63         System.out.println(ageMap.toString());
     64         // {18=[姓名:张三年龄:18身高:180性别:男], 19=[姓名:李四年龄:19身高:170性别:女, 姓名:王五年龄:19身高:170性别:男], 20=[姓名:赵六年龄:20身高:180性别:女, 姓名:陈七年龄:20身高:181性别:男]}
     65     }
     66 }
     67 
     68 
     69 class Student implements Comparable<Student>  {    
     70     int age;
     71     int height;    
     72     char sex;
     73     String name;
     74     Student(){}
     75     Student(int age,int height,char sex,String name){
     76         this.age = age;
     77         this.height = height;
     78         this.sex = sex;
     79         this.name = name;
     80     }
     81     
     82     public String toString() {
     83         return "姓名:"+name+"年龄:"+age+"身高:"+height+"性别:"+sex;
     84 
     85         }
     86     
     87     @Override
     88     public int compareTo(Student stu) {
     89         if (this.getAge()==stu.getAge()) {
     90             return this.getHeight()-stu.getHeight();
     91         } else {
     92             return this.getAge()-stu.getAge();
     93         }
     94     }
     95     
     96     public int getAge() {
     97         return age;
     98     }
     99 
    100     public int getHeight() {
    101         return height;
    102     }
    103 
    104     public char getSex() {
    105         return sex;
    106     }
    107 
    108     public String getName() {
    109         return name;
    110     }
    111 
    112     
    113 }

    一、filter

    stream接口中定义为  Stream<T> filter(Predicate<? super T> predicate);

    因此,我们使用filter则需要传入Predicate断言语句,预先编译好的还是lambda表达式都行

    (1)利用lambda表达式实现

    1         List<Student> res1 = list.stream().filter(stu->stu.getSex()=='男').collect(Collectors.toList());
    2         System.out.println(res1.toString());//  [姓名:张三年龄:18身高:180性别:男, 姓名:王五年龄:19身高:170性别:男, 姓名:陈七年龄:20身高:181性别:男]

    注意最后我们利用collect(Collectors.toList())又重新将stream流转换回list

    (2)设定好Predicate后作为参数传入

    1         Predicate<Student> stuFilter = (stu->stu.getSex()=='女');
    2         List<Student> res2 = list.stream().filter(stuFilter).collect(Collectors.toList());
    3         System.out.println(res2.toString());// [姓名:李四年龄:19身高:170性别:女, 姓名:赵六年龄:20身高:180性别:女]

    (3)利用Optional实现特定的查找功能(Optional可以预防空指针的出现,注意isPresent用法)

    1         //  Optional的教程可以看菜鸟教程的这边速通讲解https://www.runoob.com/java/java8-optional-class.html
    2         Optional<Student> firstA = res1.stream().filter(stu->stu.getHeight()==180).findFirst();
    3         System.out.println(firstA.get());// 姓名:张三年龄:18身高:180性别:男
    4         
    5         Optional<Student> firstAny = res2.stream().filter(stu->stu.getSex()=='女').findAny();
    6         System.out.println(firstAny.isPresent() ? firstAny.get():"对象为空");// 姓名:李四年龄:19身高:170性别:女

    (4)计数(注意count()的返回是long类型的,使用时需要注意类型转换)

    1         int femaleCount = (int) list.stream().filter(stuFilter).count();
    2         System.out.println("femaleCount="+femaleCount);// femaleCount=2

    二、sorted

    stream接口中定义sorted为 Stream<T> sorted();与 Stream<T> sorted(Comparator<? super T> comparator);

    要想使用sorted()则需要实现Comparable,否则会报错,要使用Comparator则需要实现自定义的比较器

    (1)使用个性化类重写的排序方法排序

    1         // 个性化类通过实现Comparable接口自定义排序规则
    2         list = list.stream().sorted().collect(Collectors.toList());
    3         System.out.println(list.toString());
    4         // [姓名:张三年龄:18身高:180性别:男, 姓名:李四年龄:19身高:170性别:女, 姓名:王五年龄:19身高:170性别:男, 姓名:赵六年龄:20身高:180性别:女, 姓名:陈七年龄:20身高:181性别:男]

    (2)使用lambda自定义排序规则

    1         // 通过lambda表达式定义排序规则(这里以身高为例)
    2         list = list.stream().sorted((stu1,stu2)->(stu1.getHeight()-stu2.getHeight())).collect(Collectors.toList());
    3         System.out.println(list.toString());
    4         // [姓名:李四年龄:19身高:170性别:女, 姓名:王五年龄:19身高:170性别:男, 姓名:张三年龄:18身高:180性别:男, 姓名:赵六年龄:20身高:180性别:女, 姓名:陈七年龄:20身高:181性别:男]

    (3)利用Comparator.comparing(function)实现比较器,进而实现多字段比较

    1         // 利用function实现比较器,进而实现多字段比较
    2         Function<Student, Integer> byAge = (Student) -> Student.getAge();
    3         Function<Student, Integer> byHeight = (Student) -> Student.getHeight();
    4         Comparator<Student> mySort = Comparator.comparing(byAge).thenComparing(byHeight);
    5         list = list.stream().sorted(mySort).collect(Collectors.toList());
    6         System.out.println(list.toString());
    7         // [姓名:张三年龄:18身高:180性别:男, 姓名:李四年龄:19身高:170性别:女, 姓名:王五年龄:19身高:170性别:男, 姓名:赵六年龄:20身高:180性别:女, 姓名:陈七年龄:20身高:181性别:男]

    三、补充

    (1)Collectors还提供了分组方法groupingBy来实现类似sql中的group by效果

    1         Map<Integer, List<Student>> ageMap = list.stream().collect(Collectors.groupingBy(Student::getAge));
    2         System.out.println(ageMap.toString());
    3         // {18=[姓名:张三年龄:18身高:180性别:男], 19=[姓名:李四年龄:19身高:170性别:女, 姓名:王五年龄:19身高:170性别:男], 20=[姓名:赵六年龄:20身高:180性别:女, 姓名:陈七年龄:20身高:181性别:男]}

    (2)Comparable与Comparator的区别

    主要在于使用方法的不同,比如

     1 public class PorblemSolution {
     2     
     3     public static void main(String[] args){
     4         List<Student> list = new ArrayList<Student>();
     5         list.add(new Student(18,180,'男',"张三"));
     6         list.add(new Student(19,170,'女',"李四"));
     7         list.add(new Student(19,170,'男',"王五"));
     8         list.add(new Student(20,180,'女',"赵六"));
     9         list.add(new Student(20,181,'男',"陈七"));
    10         
    11         // 使用Comparable
    12         list = list.stream().sorted().collect(Collectors.toList());
    13         
    14         // 使用Comparator
    15         Collections.sort(list,new Student());
    16 
    17     }
    18 }
    19 
    20 
    21 class Student  implements  Comparable<Student>,Comparator<Student>{    
    22     int age;
    23     int height;    
    24     char sex;
    25     String name;
    26     Student(){}
    27     Student(int age,int height,char sex,String name){
    28         this.age = age;
    29         this.height = height;
    30         this.sex = sex;
    31         this.name = name;
    32     }
    33     
    34     public String toString() {
    35         return "姓名:"+name+"年龄:"+age+"身高:"+height+"性别:"+sex;
    36 
    37         }
    38     
    39     @Override
    40     public int compareTo(Student stu) {
    41         if (this.getAge()==stu.getAge()) {
    42             return this.getHeight()-stu.getHeight();
    43         } else {
    44             return this.getAge()-stu.getAge();
    45         }
    46     }
    47     
    48     @Override
    49     public int compare(Student stu1, Student stu2) {
    50         if (stu1.getHeight()==stu2.getHeight()) {
    51             return stu1.getAge()-stu2.getAge();
    52         } else {
    53             return stu1.getHeight()-stu2.getHeight();
    54         }
    55     }
    56     
    57     public int getAge() {
    58         return age;
    59     }
    60 
    61     public int getHeight() {
    62         return height;
    63     }
    64 
    65     public char getSex() {
    66         return sex;
    67     }
    68 
    69     public String getName() {
    70         return name;
    71     }
    72     
    73 }
    争取早日不再是一只菜鸡
  • 相关阅读:
    J
    I
    uva122 二叉树的实现和层次遍历(bfs)
    A
    HDU 波峰
    2239: 童年的圣诞树
    1734: 堆(DFS)
    1731: 矩阵(前缀和)
    1733: 旋转图像(模拟)
    1728: 社交网络(概率问题 组合数/排列数)
  • 原文地址:https://www.cnblogs.com/jchen104/p/15039849.html
Copyright © 2011-2022 走看看