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


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

    一、Stream流

    1.终止操作 - 归约

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

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

    方法描述
    reduce( T identity , BinaryOperator accumulator)参数:(初始值,结合逻辑)
    reduce(BinaryOperator 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;
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    public enum Course {
    
    	JAVA,HTML,PYTHON;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    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);
    		
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    2.终止操作 - 收集

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

    方法描述
    collect(Collector 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);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184

    二、并行流与串行流

    并行流就是把一个内容拆分成多个数据块,并用不同的线程分别处理每个数据块的流。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);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    三、Optional

    Optional类(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 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 mapper)
    		Optional<String> map = op.map(Student::getName);
    		System.out.println(map.get());
    		
    		//与map 类似,要求返回值必须是Optional
    		//flatMap(Function> mapper)
    		Optional<String> flatMap = op.flatMap((e)->Optional.of(e.getName()));
    		System.out.println(flatMap.get());
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

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

    从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("接口中的默认方法");
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

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

    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() {
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    五、日期组件

    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
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99

    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);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    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);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    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);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    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();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    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();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    六、重复注解及类型注解

    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){}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    //作者注解
    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();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    //作者注解的容器
    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();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  • 相关阅读:
    JAVA反射机制详解
    《Java 编写基于 Netty 的 RPC 框架》
    笔记-python reduce 函数
    发布以太坊测试网络中的第一笔交易
    江西农业大学择校分析(附23招生简章)
    【Java实战】泄露用户隐私被罚巨款?系统被攻击?如何避免?
    (c语言进阶)数据存储——浮点型存储
    linux磁盘共享
    mysql回表查询和索引覆盖
    【Python深度学习】目标检测和语义分割的区别
  • 原文地址:https://blog.csdn.net/GL280599ZL/article/details/127706626