Stream + 并行流 +Optional +接口的方法 +日期组件+重复注解及类型注解

雨霖先森 2022-11-05 17:59:10

Stream + 并行流 +Optional +接口的方法 +日期组件+重复注解及类型注解

一、Stream流

1.终止操作 - 归约

归约:将流中的元素反复结合起来,得到一个值

map+reduce的连接通常称为map_reduce模式,因Google用它进行网络搜索而出名

方法描述
reduce( T identity , BinaryOperator<T> accumulator)参数:(初始值,结合逻辑)
reduce(BinaryOperator<T> accumulator)参数:(结合逻辑)
public class Student implements Comparable<Student>{
​
    private String name;
    private int age;
    private double salary;
    private Course course;
    
    public Student() {
    }
    
    public Student(String name, int age, double salary, Course course) {
        this.name = name;
        this.age = age;
        this.salary = salary;
        this.course = course;
    }
​
​
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public int getAge() {
        return age;
    }
​
    public void setAge(int age) {
        this.age = age;
    }
​
    public double getSalary() {
        return salary;
    }
​
    public void setSalary(double salary) {
        this.salary = salary;
    }
​
    public Course getCourse() {
        return course;
    }
​
    public void setCourse(Course course) {
        this.course = course;
    }
    
    
​
    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + ", salary=" + salary + ", course=" + course + "]";
    }
​
    @Override
    public int hashCode(){
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((course == null) ? 0 : course.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        long temp;
        temp = Double.doubleToLongBits(salary);
        result = prime * result + (int)(temp ^ (temp >>> 32) );
        return result;
    }
    
    @Override
    public boolean equals(Object obj) {
        if(this == obj)
            return true;
        if(obj == null)
            return false;
        if(getClass() != obj.getClass())
            return false;
        Student other = (Student) obj;
        if(age != other.age)
            return false;
        if(course != other.course)
            return false;
        if (name == null) {
            if (other.name != null) 
                return false;
        } else if(!name.equals(other.name))
            return false;
        if(Double.doubleToLongBits(salary) != Double.doubleToLongBits(other.salary))
            return false;
        return true;
    }
    @Override
    public int compareTo(Student o) {
        if(this == o){
            return 0;
        }
        if (this.age != o.age) {
            return Integer.compare(this.age, o.age);
        }
        return 1;
    }
​
}
public enum Course {
​
    JAVA,HTML,PYTHON;
}
​
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
​
import org.junit.Test;
​
public class Test01 {
​
    List<Integer> numList = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
    List<Student> stuList = Arrays.asList(
            new Student("张三", 28, 4800,Course.JAVA),
            new Student("李四", 36, 7200,Course.JAVA),
            new Student("王五", 19, 9600,Course.HTML),
            new Student("赵六", 42, 6100,Course.HTML),
            new Student("孙七", 23, 9600,Course.PYTHON),
            new Student("吴八", 31, 3000,Course.PYTHON),
            new Student("李四", 36, 7200,Course.JAVA));
    
    @Test
    public void test01(){
        //需求:获取numList集合中元素的总和
        Integer reduce = numList.stream().reduce(0, (x,y)->x+y);
        System.out.println(reduce);
        
    }
    
    @Test
    public void test02(){
        //需求:获取stuList集合中所有学生工资总和
        Optional<Double> reduce = stuList.stream().map(Student::getSalary).reduce((salary1,salary2)->salary1+salary2);
        Double sum = reduce.get();
        System.out.println(sum);
        
    }
}

2.终止操作 - 收集

收集:将流转换为其他形式。接收一个Collector接口的实现,用于给Stream中元素做汇总的方法

方法描述
collect(Collector<? super T, A, R> collector)把元素放入Collector集合中
import java.util.ArrayList;
import java.util.Arrays;
import java.util.DoubleSummaryStatistics;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
​
import org.junit.Test;
​
public class Test02 {
    List<Student> stuList = Arrays.asList(
            new Student("张三", 28, 4800,Course.JAVA),
            new Student("李四", 36, 7200,Course.JAVA),
            new Student("王五", 19, 9600,Course.HTML),
            new Student("赵六", 42, 6100,Course.HTML),
            new Student("孙七", 23, 9600,Course.PYTHON),
            new Student("吴八", 31, 3000,Course.PYTHON),
            new Student("李四", 36, 7200,Course.JAVA));
    
    @Test
    public void test01(){
        //需求1:把当前学生姓名提取出来,并把数据放入List集合中
        List<String> list = stuList.stream().map((stu)->stu.getName()).collect(Collectors.toList());
        for (String name : list) {
            System.out.println(name);
        }
    }
    
    @Test
    public void test02(){
        //需求2:把当前学生姓名提取出来,并把数据放入Set集合中
        Set<String> set = stuList.stream().map((stu)->stu.getName()).collect(Collectors.toSet());
        for (String name : set) {
            System.out.println(name);
        }
    }
    
    @Test
    public void test03(){
        //需求3:把当前学生姓名提取出来,并把数据放入指定集合中
        ArrayList<String> arrayList = stuList.stream().map((stu)->stu.getName()).collect(Collectors.toCollection(ArrayList::new));
        for (String name : arrayList) {
            System.out.println(name);
        }
    }
    
    @Test
    public void test04(){
        //需求4:收集/获取学生个数
        Long count = stuList.stream().collect(Collectors.counting());
        System.out.println(count);
    }
    
    @Test
    public void test05(){
        //需求5:收集/获取学生平均工资
        Double avg = stuList.stream().collect(Collectors.averagingDouble(Student::getSalary));
        System.out.println(avg);
    }
    
    @Test
    public void test06(){
        //需求6:收集/获取学生总工资
         Double sum = stuList.stream().collect(Collectors.summingDouble(Student::getSalary));
         System.out.println(sum);
    }
    
    @Test
    public void test07(){
        //需求7:收集/获取学生工资最大值
        Optional<Double> maxOptional = stuList.stream().map((stu)->stu.getSalary()).collect(Collectors.maxBy(Double::compareTo));
        Double max = maxOptional.get();
        System.out.println(max);
    }
    
    @Test
    public void test08(){
        //需求8:收集/获取学生工资最大值
        Optional<Double> minOptional = stuList.stream().map((stu)->stu.getSalary()).collect(Collectors.minBy(Double::compareTo));
        Double min = minOptional.get();
        System.out.println(min);
    }
    
    @Test
    public void test09(){
        //需求9:收集/获取工资最多的学生信息
        Optional<Student> stuOptional = stuList.stream().collect(Collectors.maxBy(
                (stu1,stu2)->Double.compare(stu1.getSalary(), stu2.getSalary())));
        Student stu = stuOptional.get();
        System.out.println(stu);
    }
    
    @Test
    public void test10(){
        //需求10:收集/获取工资最少的学生信息
        Optional<Student> stuOptional = stuList.stream().collect(Collectors.minBy(
                (stu1,stu2)->Double.compare(stu1.getSalary(), stu2.getSalary())));
        Student stu = stuOptional.get();
        System.out.println(stu);
    }
    
    @Test
    public void test11(){
        //需求11:按照学科分组
        Map<Course, List<Student>> map = stuList.stream().collect(Collectors.groupingBy(Student::getCourse));
        Set<Entry<Course,List<Student>>> entrySet = map.entrySet();
        for (Entry<Course, List<Student>> entry : entrySet) {
            System.out.println(entry);
        }
    }
    
    @Test
    public void test12(){
        //需求12:按照学科分组,在按照年龄分组
        Map<Course, Map<String, List<Student>>> map = stuList.stream().collect(Collectors.groupingBy(Student::getCourse,Collectors.groupingBy((obj)->{
            Student stu = (Student)obj;
            int age = stu.getAge();
            if(age<28){
                return "青年";
            }
            if(age<40){
                return "中年";
            }
            return "老年";
        })));
        Set<Entry<Course,Map<String,List<Student>>>> entrySet = map.entrySet();
        for (Entry<Course, Map<String, List<Student>>> entry : entrySet) {
            Course key = entry.getKey();
            Map<String, List<Student>> value = entry.getValue();
            System.out.println(key + " -- " + value);
        }
    }
    
    @Test
    public void test13(){
        //需求13:按照工资5000为标准分区
        Map<Boolean, List<Student>> map = stuList.stream().collect(Collectors.partitioningBy((stu)->{
            if(stu.getSalary() > 5000){
                return true;
            }
            return false;
        }));
        Set<Entry<Boolean,List<Student>>> entrySet = map.entrySet();
        for (Entry<Boolean, List<Student>> entry : entrySet) {
            System.out.println(entry);
        }
        
    }
    
    @Test
    public void test14(){
        //需求14:获取学生工资信息,再获取总值、平均值、最大值、最小值
        
        //DoubleSummaryStatistics对象 -- 学生工资信息
        DoubleSummaryStatistics collect = stuList.stream().collect(Collectors.summarizingDouble(Student::getSalary));
    
        double sum = collect.getSum();
        double avg = collect.getAverage();
        double max = collect.getMax();
        double min = collect.getMin();
        System.out.println(sum);
        System.out.println(avg);
        System.out.println(sum);
        System.out.println(max);
        System.out.println(min);
    }
    
    @Test
    public void test15(){
        //需求15:拼接学生姓名
        
        String str1 = stuList.stream().map(Student::getName).collect(Collectors.joining());
        System.out.println(str1);
        
        String str2= stuList.stream().map(Student::getName).collect(Collectors.joining(","));
        System.out.println(str2);
        
        String str3= stuList.stream().map(Student::getName).collect(Collectors.joining(",", "-", "-"));
        System.out.println(str3);
    }
}

二、并行流与串行流

并行流就是把一个内容拆分成多个数据块,并用不同的线程分别处理每个数据块的流。Java8中将并行进行了优化,我们可以很容易的对数据进行并行操作。Stream API可以声明性地通过 parallel() - 并行流 与sequential()-顺序流 之间进行切换。

注意

  1. 默认为顺序流/串行流

  2. 并行流一般在大数据搜索里使用到

  3. JDK1.8之前也有并行流,叫做Fork/Join并行计算框架

import java.util.stream.LongStream;
​
public class Test03 {   
    public static void main(String[] args) {
        
        //需求:计算1-10000000L之和
        
        long sum = LongStream.range(1, 10000000L).//获取Stream流对象,该对象中存储了1~10000000L的数字
                parallel().//设置该流为并行流(底层会给我们拆分成多个线程去计算)
                reduce(0, (x,y)->x+y);//归约
        System.out.println(sum);
    }
}

三、Optional

Optional<T>类(java. util. Optional)是一个容器类,代表一个存在或不存在的值,原来用null表示一个值不存在,现在Optional可以更好的表达这个概念。并且可以避免空指针异常

此类的设计就是更好的避免空指针异常

方法描述
Optional.of(T t)创建一个Optional实例
Optional.empty()创建一 个空的 Optional实例
Optional.ofNullable(T t)若t不为null,创建Optional实例,否则创建空实例
get()获取Optional实例里的对象
isPresent()判断是否包含值
orElse(T t)如果调用对象包含值, 返回该值,否则返回t
orElseGet(Supplier s)如果调用对象包含值,返回该值,否则返回s获取的值
map(Function f)如果有值对其处理,并返回处理后的Optional,否则返回optional. empty()
flatMap(Function mapper)与map 类似,要求返回值必须是Optional
import java.util.Optional;
​
import com.qf.stream.Student;
​
public class Test01 {
​
    public static void main(String[] args) {
        //获取Optional的对象,该对象中存储了一个学生对象
//      Optional<Student> optional = Optional.of(new Student());
    
        //获取Optional对象中的学生对象
//      Student stu = optional.get();
//      System.out.println(stu);
        
        //创建Optional的对象,该对象中没有存储了学生对象
        Optional<Object> optional = Optional.empty();
        
        //获取Optional对象中的学生对象,但是Optional对象中没有学生对象,就创建个学生对象(最大化限度的减少了空指针异常)
        Object stu = optional.orElse(new Student());
        System.out.println(stu);
        
        //不同情况下可以返回不同对象,orElseGet()比orElse()可变性更强
        boolean bool = true;
        stu = op.orElseGet(()->{
            if(bool){
                return new Student("刘备", 26, 8888, Course.JAVA);
            }else{
                return new Student("甘夫人", 26, 8888, Course.JAVA);
            }
        });
        
        //获取原容器中的某个值并返回新容器中
        //map(Function<? super T, ? extends U> mapper)
        Optional<String> map = op.map(Student::getName);
        System.out.println(map.get());
        
        //与map 类似,要求返回值必须是Optional
        //flatMap(Function<? super T, Optional<U>> mapper)
        Optional<String> flatMap = op.flatMap((e)->Optional.of(e.getName()));
        System.out.println(flatMap.get());
    }
}

四、接口的默认方法与静态方法

从JDK1.8开始,接口中可以有默认方法,既default修饰的方法,此方法可以让接口的实现类所调用,而接口中的静态方法直接用接口名调用即可

接口默认方法的”类优先”原则:

如果一个接口中定义了一个默认方法,而接口实现类的父类定义了一个同名的方法时,选择父类中的方法

public class Test01 {
​
    public static void main(String[] args) {
        
        B b = new B();
        b.method();
    }
}
​
class A{
    public void method(){
        System.out.println("父类中的method方法");
    }
}
​
class B extends A implements I1{}
interface I1{
    default void method(){
        System.out.println("接口中的默认方法");
    }
}

接口冲突:如果一个父接口提供一个默认方法,而另一个接口也提供了一个具有相同名称和参数列表的方法(不管方法是否是默认方法),那么必须覆盖该方法来解决冲突

public class Test01 {
​
    public static void main(String[] args) {
        
    }
}
​
interface I1{
    default void method(){
        System.out.println("I1接口中的默认方法");
    }
}
​
interface I2 extends I1{
    public void method();
}
​
class A implements I1,I2{
    
    @Override
    public void method() {
    }
}

五、日期组件

JDK1.8提供的新日期类都是不可变的,既不管怎么样的改变,都会产生一个新的实例,他们都是线程安全的

日期组件遵循与IOS-8601世界时间标准

1.组件简介

包路径类名描述
java.time 针对日期和时间操作的包
 LocalDate用于表示日期的类
 LocalTime用于表示时间的类
 LocalDateTime用于表示日期时间的类
 Instant时间戳类(1970.1.1 0:0:0 到现在的毫秒数
 Period两个日期间隔类
 Duration两个时间间隔类
java.time.chrono 针对日期时间特殊格式操作的包
java.time.format 针对时间日期时间格式化操作的包
 DateTimeFormatter格式化日期时间类
java.time.temporal 针对时间矫正操作的包
java.time.zone 针对时区操作的包

2.日期时间类、时间戳、间隔类

import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.Period;
import java.time.ZoneOffset;
​
import org.junit.Test;
​
public class Test01 {
​
    @Test
    public void test01(){
        //LocalDate LocalTime LocalDateTime
        //这三个日期类的使用大致一样
​
        //获取当前日期时间对象
        LocalDateTime ldt1 = LocalDateTime.now();
        System.out.println(ldt1);//2022-10-31T11:23:18:102
​
        //获取指定日期时间对象
        LocalDateTime ldt2 = LocalDateTime.of(2020, 1, 23, 8, 30, 10, 10);
        System.out.println(ldt2);//2020-1-23T8:30:10:10
​
        //获取ldt1推后的时间日期对象
        LocalDateTime ldt3 = ldt1.plusYears(2);//退后两年
        System.out.println(ldt3);////2024-10-31T11:23:18:102
​
        //获取ldt1提前的时间日期对象
        LocalDateTime ldt4 = ldt3.minusMonths(2);//提前两个月
        System.out.println(ldt4);//2024-8-31T11:23:18:102
​
        //获取日期中的单个信息
        System.out.println(ldt4.getYear());
        System.out.println(ldt4.getMonthValue());
        System.out.println(ldt4.getDayOfMonth());
        System.out.println(ldt4.getHour());
        System.out.println(ldt4.getMinute());
        System.out.println(ldt4.getSecond());
    }
​
    @Test
    public void test02(){
        //使用时间戳(从1970年1月1日0:0:0到现在的毫秒值)
​
        //默认创建UTC(世界标准时间)时区的时间戳对象
        Instant now1 = Instant.now();
        System.out.println(now1);//2022-10-31T03:27:55.921Z
​
        //获取偏移8小时的偏移日期时间对象
        OffsetDateTime odt = now1.atOffset(ZoneOffset.ofHours(8));
        System.out.println(odt);//2022-10-31T11:27:55.921+08:00
​
        //获取时间戳的毫秒值形式
        System.out.println(now1.toEpochMilli());
​
        //获取一个1970年1月1日0:0:0 往后退1秒的时间戳对象
        Instant now2 = Instant.ofEpochSecond(1);
        System.out.println(now2);
    }
​
    @Test
    public void test03() throws InterruptedException {
        //Duration:时间间隔类
​
        Instant now1 = Instant.now();
        Thread.sleep(1000);
        Instant now2 = Instant.now();
​
        //获取时间间隔类对象
        Duration duration1 = Duration.between(now1, now2);
        System.out.println(duration1.toMillis());
​
        System.out.println("-----------------------------");
​
        LocalTime lt1 = LocalTime.now();
        Thread.sleep(1000);
        LocalTime lt2 = LocalTime.now();
        //获取时间间隔类对象
        Duration duration2 = Duration.between(lt1, lt2);
        System.out.println(duration2.toMillis());
    }   
    @Test
    public void test04() throws InterruptedException {
        //Period:日期间隔类
        LocalDate ld1 = LocalDate.of(2021, 12, 28);
        Thread.sleep(1000);
        LocalDate ld2 = LocalDate.of(2022, 10, 31);
​
        //获取日期间隔类对象
        Period period = Period.between(ld1, ld2);
​
        System.out.println(period.getYears());//0
        System.out.println(period.getMonths());//10
        System.out.println(period.getDays());//3
    }
}

3.日期时间格式化类-DateTimeFormatter

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
​
import org.junit.Test;
​
public class Test02 {
​
    @Test
    public void test01() {
        //格式化日期时间类
        LocalDateTime ldt1 = LocalDateTime.now();//2022-10-31T11:35:18:122
        
        //获取本地标准的日期时间格式化对象
        DateTimeFormatter dtf1 = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
        String strDateTime1 = ldt1.format(dtf1);//格式化时间日期
        System.out.println(strDateTime1);//2022-10-31T11:35:18:122
        
        //自定义日期时间格式化对象
        DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
        String strDateTime2 = ldt1.format(dtf2);//格式化时间日期
        System.out.println(strDateTime2);
        
        //将指定格式的字符串解析成LocalDateTime对象
        LocalDateTime parse = LocalDateTime.parse("2020年03月12日 11:04:14", dtf2);
        System.out.println(parse);
    }
}

4.时间矫正器类-TemporalAdjuster

import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
​
import org.junit.Test;
​
public class Test04 {
​
    @Test
    public void test01() {
        //时间矫正器
        LocalDateTime ldt1 = LocalDateTime.now();//2022-10-31T14:03:18:122
​
        //设置指定月份
        LocalDateTime ldt2 = ldt1.withMonth(12);
        System.out.println(ldt2);//2022-12-31T14:03:18:122
​
        //设置下一个周末
        LocalDateTime ldt3 = ldt1.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
        System.out.println(ldt3);
​
        //自定义时间矫正器:设置下一个工作日
        LocalDateTime ldt4 = ldt1.with((temporal)->{
            //获取到日期时间对象
            LocalDateTime ldt = (LocalDateTime) temporal;
            //获取周几?
            DayOfWeek week = ldt.getDayOfWeek();
            if(week.equals(DayOfWeek.FRIDAY)){//周五
                return ldt.plusDays(3);//往后推3天
            }else if(week.equals(DayOfWeek.SATURDAY)){//周六
                return ldt.plusDays(2);//往后推2天
            }else{
                return ldt.plusDays(1);//往后推1天
            }
        });
        System.out.println(ldt4);
    }
}

5.时区类

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Set;
​
import org.junit.Test;
​
public class Test03 {
​
    @Test
    public void test01() {
        //时区类 
​
        //获取所有时区字符串
        Set<String> set = ZoneId.getAvailableZoneIds();
        for (String str : set) {
            System.out.println(str);
        }
        
        System.out.println("-------------");
        
        //获取指定时区的日期时间对象
        LocalDateTime ldt1 = LocalDateTime.now(ZoneId.of("Asia/Tokyo"));
        System.out.println(ldt1);
        
        //获取指定时区的日期时间对象 + 偏移量
        LocalDateTime ldt2 = LocalDateTime.now(ZoneId.of("Asia/Tokyo"));
        ZonedDateTime zonedDateTime = ldt2.atZone(ZoneId.of("Asia/Tokyo"));
        System.out.println(zonedDateTime);
    }
}

6.传统日期格式化的线程问题

需求:让多线程同时去解析日期

1.使用JDK1.7时的日期时间类会出现问题

错误示范

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
​
public class Test01 {
    public static void main(String[] args) throws Exception {
        
        //创建日期格式化类的对象   
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        
        //创建带有返回值的任务类的对象
        Callable<Date> task = new Callable<Date>() {
            @Override
            public Date call() throws Exception {
                Date date = sdf.parse("20200123");
                return date;
            }
        };
        
        //创建线程池
        ThreadPoolExecutor pool = new ThreadPoolExecutor(10, 10, 0L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        
        //提交任务
        ArrayList<Future<Date>> list = new ArrayList<>();
        for (int i = 1; i <= 10; i++) {
            Future<Date> future = pool.submit(task);
            list.add(future);
        }
        
        //遍历集合
        for (Future<Date> future : list) {
            Date date = future.get();
            System.out.println(date);
        }
        
        //关闭线程池
        pool.shutdown();
    }
}

2.使用JDK1.8的日期时间类

正确示范

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
​
public class Test02 {
    public static void main(String[] args) throws Exception {
        
        //创建日期格式化类的对象   
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
        
        //创建带有返回值的任务类的对象
        Callable<LocalDate> task = new Callable<LocalDate>() {
            @Override
            public LocalDate call() throws Exception {
                
                LocalDate localDate = LocalDate.parse("20200123", dtf);
                return localDate;
            }
        };
        
        //创建线程池
        ThreadPoolExecutor pool = new ThreadPoolExecutor(10, 10, 0L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        
        //提交任务
        ArrayList<Future<LocalDate>> list = new ArrayList<>();
        for (int i = 1; i <= 10; i++) {
            Future<LocalDate> future = pool.submit(task);
            list.add(future);
        }
        
        //遍历集合
        for (Future<LocalDate> future : list) {
            LocalDate date = future.get();
            System.out.println(date);
        }
        
        //关闭线程池
        pool.shutdown();
    }
}

六、重复注解及类型注解

jdk1.8开始可以重复注解

ps:一个类可有多个同样的注解

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
​
@Author(name="G")
@Author(name="Z")
public class Test01 <@Author(name="L") T>{
​
    public static void main(String[] args) throws Exception {
        
        Class<?> clazz = Test01.class;
        
        //利用反射获取类上的重复注解
        Author[] typeAuthors = clazz.getAnnotationsByType(Author.class);
        for (Author author : typeAuthors) {
            String name = author.name();
            System.out.println(name);
        }
        
        //利用反射获取方法中参数上的注解
        Method method = clazz.getDeclaredMethod("method", String.class);
        Parameter[] parameters = method.getParameters();//获取方法上的参数对象
        for (Parameter parameter : parameters) {
            //获取参数上的重复注解
            Author[] parameterAuthors = parameter.getAnnotationsByType(Author.class);
            for (Author author : parameterAuthors) {
                String name = author.name();
                System.out.println(name);
            }
            
            //获取参数类型
            Class<?> type = parameter.getType();
            System.out.println(type);
            //获取参数名(参数名不会编译到class文件)
            String name = parameter.getName();
            System.out.println(name);
            
        }
    }
    public void method(@Author(name="GL") @Author(name="ZL")String xxx){}
}
//作者注解
import static java.lang.annotation.ElementType.*;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
​
@Repeatable(Authors.class)
@Target({TYPE,PARAMETER,TYPE_PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Author {
    
    String name();
}
//作者注解的容器
import static java.lang.annotation.ElementType.*;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
​
@Target({TYPE,PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Authors {
​
    Author[] value();
}
...全文
81 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

51,412

社区成员

发帖
与我相关
我的任务
社区描述
Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
  • Java相关社区
  • 小虚竹
  • 谙忆
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧