• 25、stream api、自定义注解


    一、什么是Stream API

    A sequence of elements supporting sequential and parallel
    aggregate operations
    Stream是一组用来处理数组、集合的API
     
    ▪ Java 8之所以费这么大功夫引入函数式编程,原因有二:
      – 代码简洁函数式编程写出的代码简洁且意图明确,使用stream接口让你从
        此告别for循环。
      – 多核友好,Java函数式编程使得编写并行程序从未如此简单,你需要的全部
        就是调用一下parallel()方法。
     

    二、Stream特性

    1:不是数据结构,没有内部存储
    2:不支持索引访问
    3:延迟计算
    4:支持并行
    5:很容易生成数组或集合(List,Set)
    6:支持过滤,查找,转换,汇总,聚合等操作
     

    三、Stream运行机制

    Stream分为 源source,中间操作,终止操作
    流的源可以是一个数组、一个集合、一个生成器方法,一个I/O通道等等。
    一个流可以有零个和或者多个中间操作,每一个中间操作都会返回
    一个新的流,供下一个操作使用。一个流只会有一个终止操作
    Stream只有遇到终止操作,它的源才开始执行遍历操作
     

    四、Stream的创建

     

    1、通过数组
    2、通过集合来
    3、通过Stream.generate方法来创建
    4、通过Stream.iterate方法来创建
    5、其他API创建
    public class StreamDemo {
    
        //通过数组来生成
        static void gen1(){
            String[] strs = {"a","b","c","d"};
            Stream<String> strs1 = Stream.of(strs);
            strs1.forEach(System.out::println);
        }
    
        //通过集合来生成
        static void gen2(){
            List<String> list = Arrays.asList("1","2","3","4");
            Stream<String> stream = list.stream();
            stream.forEach(System.out::println);
        }
    
        //generate
        static void gen3(){
            Stream<Integer> generate = Stream.generate(() -> 1); // generate(Supplier<T> s)返回无限顺序无序流, 其中每个元素由提供的Suppliter
            generate.limit(5).forEach(System.out::println); // 没有limit 程序就不会中断 无限的
        }
    
        //使用iterator
        static void gen4() {
            Stream<Integer> iterate = Stream.iterate(1, x -> x + 1);
            iterate.limit(5).forEach(System.out::println);
        }
    
    
        //其他方式
        static void gen5(){
            String str = "abcd";
            IntStream stream =str.chars();
            stream.forEach(System.out::println);
        }
        public static void main(String[] args) {
            //stream生成的操作
            gen1();
            gen2();
            gen3();
            gen4();
            gen5();
        }  
    }

    打印结果为:

    /*
    a
    b
    c
    d
    1
    2
    3
    4
    1
    1
    1
    1
    2
    3
    97
    98
    99
    100
    
    Process finished with exit code 0
    */

    五、Stream常用API

    中间操作
      过滤 filter
      去重 distinct
      排序 sorted
      截取 limit、skip
      转换 map/flatMap
      其他 peek
     
    终止操作
      循环 forEach
      计算 min、max、count、 average
      匹配 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny
      汇聚 reduce
      收集器 toArray collect
     
    示例1:
    public class StreamDemo {
        public static void main(String[] args) {//中间操作:如果调用方法之后返回的结果是Stream对象就意味着是一个中间操作
            Arrays.asList(1,2,3,4,5).stream().filter((x)->x%2==0).forEach(System.out::println);
            //求出结果集中所有偶数的和
            int count = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9).stream().filter(x -> x % 2 == 0).mapToInt(x->x).sum();
            System.out.println(count);
            //求集合中的最大值
            List<Integer> list = Arrays.asList(1,2, 3,4, 5, 6);
            Optional<Integer> max = list.stream().max((a, b) -> a - b);
            System.out.println(max.get());
            //求集合的最小值
            System.out.println(list.stream().min((a, b) -> a-b).get());
    
            Optional<Integer> any = list.stream().filter(x -> x % 2 == 0).findAny(); // 任意取一个
            System.out.println(any.get());
    
            Optional<Integer> first = list.stream().filter(x -> x % 10 == 6).findFirst();
            System.out.println(first.get());
    
            Stream<Integer> integerStream = list.stream().filter(i -> {
                System.out.println("运行代码");
                return i % 2 == 0;
            });
            System.out.println(integerStream.findAny().get());
        }  
    }

    打印结果为:

    /*
    2
    4
    20
    6
    1
    2
    6
    运行代码
    运行代码
    2
    */

    为什么会打印两次 “运行代码”

    把每一个元素分别取出来,执行中间操作到终止操作
    1 拿出来 中间操作 打印一次 “运行代码”
    2 拿出来 中间操作 打印一次 “运行代码”
    满足条件,findAny终止操作,不再继续向下
    如果是
    List<Integer> list = Arrays.asList(1, 3, 5, 6);
    呢, 打印几次?
    结果是四次
    6满足条件终止操作
     
    相当于流水线,拿出1个 走完全部过程 走filter、FindAny

     示例2:

    public class StreamDemo {
        public static void main(String[] args) {
            List<Integer> list = Arrays.asList(1,2, 3,4, 5, 6);
            //获取最大值和最小值但是不使用min和max方法
            Optional<Integer> min = list.stream().sorted().findFirst();
            System.out.println(min.get());
            Optional<Integer> max2 = list.stream().sorted((a, b) -> b - a).findFirst();
            System.out.println(max2.get());
    
            Arrays.asList("java","c#","python","scala").stream().sorted().forEach(System.out::println);
            Arrays.asList("java","c#","python","scala").stream().sorted((a,b)->a.length()-b.length()).forEach(System.out::println);
        } 
    
    }

    打印结果为:

    /*
    1
    6
    c#
    java
    python
    scala
    c#
    java
    scala
    python
    
    Process finished with exit code 0
    */

     示例3:

    public class StreamDemo {
        public static void main(String[] args) {
            List<Integer> list = Arrays.asList(1,2, 3,4, 5, 6);
            //想将集合中的元素进行过滤同时返回一个集合对象
            List<Integer> collect = list.stream().filter(x -> x % 2 == 0).collect(Collectors.toList());
            collect.forEach(System.out::println);
        } 
    
    }

    打印结果为:

    /*
    2
    4
    6
    
    Process finished with exit code 0
    */

     示例4:

    public class StreamDemo {
        public static void main(String[] args) {
            List<Integer> list = Arrays.asList(1,2, 3,4, 5, 6);
            //去重操作
            Arrays.asList(1,2,3,3,3,4,5,2).stream().distinct().forEach(System.out::println);
            System.out.println("---------------");
            Arrays.asList(1,2,3,3,3,4,5,2).stream().collect(Collectors.toSet()).forEach(System.out::println);
        } 
    
    }

     示例5:

    public class StreamDemo {
        public static void main(String[] args) {
            //打印20-30这样的集合数据
            Stream.iterate(1,x->x+1).limit(50).skip(20).limit(10).forEach(System.out::println); // skip跳过20个输出10个
    
            String str ="11,22,33,44,55"; // 求和
            System.out.println(Stream.of(str.split(",")).mapToInt(x -> Integer.valueOf(x)).sum());
            System.out.println(Stream.of(str.split(",")).mapToInt(Integer::valueOf).sum());
            System.out.println(Stream.of(str.split(",")).map(x -> Integer.valueOf(x)).mapToInt(x -> x).sum());
            System.out.println(Stream.of(str.split(",")).map(Integer::valueOf).mapToInt(x -> x).sum());
        } 
    
    }

    打印结果为:

    /*
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    165
    165
    165
    165
    
    Process finished with exit code 0
    */

     示例6:

    public class StreamDemo {
        public static void main(String[] args) {
            //创建一组自定义对象
            String str2 = "java,scala,python";
            Stream.of(str2.split(",")).map(x->new com.mashibing.stream.Person(x)).forEach(System.out::println);
            Stream.of(str2.split(",")).map(com.mashibing.stream.Person::new).forEach(System.out::println);
            Stream.of(str2.split(",")).map(x-> com.mashibing.stream.Person.build(x)).forEach(System.out::println);
            Stream.of(str2.split(",")).map(com.mashibing.stream.Person::build).forEach(System.out::println); // 静态方法的方式
        } 
    
    }
    public class Person {
        private String name;
    
        public Person() {
        }
    public Person(String name) { this.name = name; } public static Person build(String name){ Person p = new Person(); p.setName(name); return p; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Deprecated public static void show(){ System.out.println("show"); } @Override public String toString() { return "Person{" + "name='" + name + '\'' + '}'; } public static void main(String[] args) { Person p = new Person(); show(); Date date = new Date(); System.out.println(date.getMinutes()); } }

    打印结果为:

    /*
    Person{name='java'}
    Person{name='scala'}
    Person{name='python'}
    Person{name='java'}
    Person{name='scala'}
    Person{name='python'}
    Person{name='java'}
    Person{name='scala'}
    Person{name='python'}
    Person{name='java'}
    Person{name='scala'}
    Person{name='python'}
    
    Process finished with exit code 0
    */

    示例7:

    public class StreamDemo {
        public static void main(String[] args) {
            String str ="11,22,33,44,55";
            //将str中的每一个数值都打印出来,同时算出最终的求和结果
            System.out.println(Stream.of(str.split(",")).peek(System.out::println).mapToInt(Integer::valueOf).sum());
        } 
    
    }

    打印结果为:

    /*
    11
    22
    33
    44
    55
    165
    
    Process finished with exit code 0
    */

    示例8:

    public class StreamDemo {
        public static void main(String[] args) {
            List<Integer> list = Arrays.asList(1,2, 3,4, 5, 6);
            System.out.println(list.stream().allMatch(x -> x>=0));
    }

    打印结果为:

    /*
    true
    
    Process finished with exit code 0
    */

    六、自定义注解

    1、什么是注解?

    ▪ Annontation是Java5开始引入的新特征,中文名称叫注解。
    ▪ 它提供了一种安全的类似注释的机制,用来将任何的信息或元数据(metadata)与程序元素(类、方法、成员变量等)进行关联。
    ▪ 为程序的元素(类、方法、成员变量)加上更直观更明了的说明,这些说明信息是与程序的业务逻辑无关,并且供指定的工具戒框架使用。
    ▪ Annontation像一种修饰符一样,应用于包、类型、构造方法、方法、成员变量、参数及本地变量的声明语句中。
    ▪ Java注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。
    ▪ 注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用。包含在java.lang.annotation 包中。

     

    2、注解的作用

    ▪ 生成文档。这是最常见的,也是java 最早提供的注解。常用的有@param @return 等  /** + 回车就会看到
    ▪ 跟踪代码依赖性,实现替代配置文件功能。
    ▪ 在编译时进行格式检查。如@override 放在方法前,如果你这个方法并不是覆盖了超类方法,则编译时就能检查出。

    3、注解的原理

    反射
     

    4、内置注解

    ▪ @Override:定义在java.lang.Override中,此注释叧适用于修饰方法,表示一个方法声明打算重写超类中的另一个方法声明
    ▪ @Deprecated:定义在java.lang.Deprecated中,此注释可以修饰方法、属性、类,表示不鼓励程序员使用这样的元素,通常
    是因为它很危险或者存在更好的选择
    ▪ @SuppressWarnings:定义在java.lang.SuppressWarnings中,用来抑制编写编译时的警告信息 比如定义一个变量没用到会是灰色,加@SuppressWarnings("all") 就会是正常的黑色

    5、元注解

    ▪ 元注解的做用是负责注解其他注解,java中定义了四个标准的meta-annotation类型,他们被用来提供对其他annotation类型作说明
    ▪ 这些类型和它们所支持的类在java.lang.annotation包中
    – @Target:用来描述注解的使用范围(注解可以用在什么地方)
    – @Retention:表示需要在什么级别保存该注释信息,描述注解的生命周期
      ▪ Source < Class < Runtime
    – @Document:说明该注解将被包含在javadoc中
    – @Inherited:说明子类可以继承父类中的该注解
     
     

    6、自定义注解

    ▪ 使用@interfac自定义注解时,自动继承了
    java.lang.annotation.Annotation接口
    ▪ 使用规则:
    – @interface用来声明一个注解,格式:public @interface 注解名{}
    – 其中的每一个方法实际上是声明了一个配置参数
    – 方法的名称就是参数的名称
    – 返回值类型就是参数的类型(返回值叧能是基本类型,Class,String,enum)
    – 可以用default来声明参数的默认值
    – 如果叧有一个参数成员,一般参数名为value
    – 注解元素必须要有值,我们定义注解元素时,经常使用空字符串,0作为默认值
     
    //target用来声明当前自定义的注解适合适用于什么地方,类,方法,变量,包。。。。
    @Target({ElementType.METHOD,ElementType.TYPE})
    //retention用来表示当前注解适用于什么环境,是源码级别还是类级别还是运行时环境,一般都是运行时环境
    @Retention(RetentionPolicy.CLASS)
    //表示该注解是否是显示在javadoc中
    @Documented
    //表示当前注解是否能够被继承
    @Inherited
    @interface MyAnnotation{
    
        //定义的方式看起来像是方法,但是实际上使用在使用注解的时候填写的参数的名称,默认的名称是value
        //自定义注解中填写的所有方法都需要在使用注解的时候,添加值,很麻烦,因此包含默认值
        String name() default "zhangsan";
        int age() default 12;
        int id() default 1;
        String[] likes() default {"a","b","c"};
    }
    //@MyAnnotation(name="hehe",age=12,id=3,likes = {"book","lol","movie"})
    @MyAnnotation
    public class MetaAnnotation {
        public void test(){
    
        }
    }
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    Flask上下文管理源码分析 ——(3)
    Flask 快速使用 进阶—— (2)
    HTML-语法
    安装kubenetes-遇到的问题总结
    CentOS7-部署kubernetes
    k8s-部署及介绍
    docker-macvlan网络
    Dom编程-左侧菜单栏设计模型实现
    JavaScript-checkbox标签-隐藏、显示、全选、取消和反选等操作
    docker-Overlay原生网络
  • 原文地址:https://www.cnblogs.com/kongxiangqun/p/16180440.html
Copyright © 2020-2023  润新知