JDK1.8新特性

本文主要介绍了JDK1.8新特性相关知识,其中包含Lambda表达式、方法引用、Stream、新时间API,在本文中结合代码对JDK1.8新特性进行了详细的分析!

一、Lambda表达式

1.简介

  • Lambda表达式(又称为闭包)是整个JAVA8发现版中最受期待的在Java语言层面上的改变.
  • lambda允许把函数作为一个参数(函数作为参数传递进方法中),或者把代码看成数据.
  • lambda表达式用于简化java中接口式的匿名内部类,被称为函数式接口的概念.函数式接口就是一个具有一个方法的普通接口,像这样的接口可以被隐式转换为lambda表达式
  • 作用: 简化代码
    要求:一个接口或抽象类中只有一个抽象方法
  • 优点:
    1,简化代码
    2,不会生成class文件
  • 缺点:
    1,有限制
    2,对新手代码阅读增加困难

2.语法

  • 格式:(参数1,参数2,…)->{方法体}
  • 注意:
    1,一个接口中只有一个方法,可以用Lambda进行简化
    2,如果一个接口中只有一个抽象方法,该接口称为函数式接口

3.Lambda表达式与函数式接口

(1)没有参数时使用lambda表达式

	代码:
        public class Test01 {
            public static void main(String[] args) {
                IEatImpl iEatImpl = new IEatImpl();
                iEatImpl.eat();
                IEat iEat = new IEat() {
                    @Override
                    public void eat() {
                        // TODO Auto-generated method stub
                        System.out.println("吃东西01");
                    }
                };
                iEat.eat();
                /**
                 * Labdma写法
                 */
                IEat iEat02 = ()->{
                    System.out.println("吃东西02");
                };
                iEat02.eat();
            }
        }
        interface IEat{
            void eat();
        }
        class IEatImpl implements IEat{
            @Override
            public void eat() {
                // TODO Auto-generated method stub
                System.out.println("吃东西");
            }
        }

(2)带有参数时使用lambda表达式

	代码:
		public class Test01 {
            public static void main(String[] args) {
                IEat iEat01 = (String foodName)->{
                	System.out.println("吃"+foodName);
                };
                iEat01.eat("大嘴巴子");
                
                IEat iEat02 = (foodName)->{
                	System.out.println("吃"+foodName);
                };
                iEat02.eat("大嘴巴子");
                //方法中只有一个参数可以忽略()不写
                IEat iEat03 = foodName->{
                	System.out.println("吃"+foodName);
                };
                iEat03.eat("大嘴巴子");
                IEat02 iEat04 = (foodName,name)->{
                	System.out.println(name+"吃"+foodName);
                };
                iEat04.eat("大嘴巴子","张三");
            }
        }
        interface IEat{
            void eat(String foodName);
        }
        interface IEat02{
            void eat(String foodName,String name);
        }

(3)代码块中只有一句代码时使用lambda表达式

代码:
        public class Test01 {
            public static void main(String[] args) {
                IEat iEat02 = ()->System.out.println("吃东西");
                iEat02.eat();
            }
        }
        interface IEat{
            void eat();
        }

(4)代码块中有多句代码时使用lambda表达式

	代码:
        public class Test01 {
            public static void main(String[] args) {
                IEat iEat = ()->{
                	System.out.println("准备干饭");
                	System.out.println("吃东西");
                	System.out.println("就餐完毕");
                };
                iEat.eat();
            }
        }
        interface IEat{
            void eat();
        }

(5)有返回值得代码块

	代码:
        public class Test01 {
            public static void main(String[] args) {
                IEat iEat = ()->{
                	System.out.println("吃东西");
                	return true;
                };
                iEat.eat();
                //有返回值得方法体只有一句代码,忽略大括号与return关键字
                IEat iEat = ()->true;
                iEat.eat();
            }
        }
        interface IEat{
            boolean eat();
        }

(6)参数中使用final关键字

	代码:
        public class Test01 {
            public static void main(String[] args) {
                IEat iEat = (final String foodName)->{
                	System.out.println("吃"+foodName);
                	return true;
                };
                iEat.eat();
            }
        }
        interface IEat{
            boolean eat(final String foodName);
        }

3.相关注解

@FunctionalInterface
作用:验证接口是否为函数接口

4常见函数式接口

接口名称			类型			方法
Consumer<T>		消费型接口		void accept(T t):操作t
Supplier<T>		供给型接口		T get():返回t
Function<T,R>	函数型接口		R apply(T t):操作t,返回r
Predicate<T>	断言型接口		boolean test(T t):操作t,返回boolean

二、方法引用

1.简介

  • 方法引用是Lambda表达式的一种简写形式
  • 要求:
    如果Lambda表达式方法体中只是调用一个特点的已经存在的方法,则可以使用方法引用

2.语法

(1)对象::实例方法

	要求:lambda传入的参数与就是所调用的方法的参数,并且方法体中只有一行代码
	代码:
		Consumer<String> consumer=s->System.out.println(s);
		consumer.accept("hello");
		Consumer<String> consumer2=System.out::println;
		consumer2.accept("world");

(2)类::静态方法

	要求:lambda传入的参数与就是所调用的方法的参数,并且方法体中只有一行代码
	代码:
		Comparator<Integer> com=(o1,o2)->Integer.compare(o1, o2);
		Comparator<Integer> com2=Integer::compare;

(3)类::实例方法

	要求:lambda传入的参数类型就是调用该方法的对象,并且方法体中只有一行代码
	代码:
		Function<Employee, String> function=e->e.getName();
		Function<Employee, String> function2=Employee::getName;
		System.out.println(function2.apply(new Employee("小明", 50000)));
		
		class Employee{
            private String name;
            private int money;
            public Employee(String name,int money) {
                this.money = money;
                this.name = name;
            }
            public String getName() {
                return name;
            }
        }

(4)类::new

	要求:lambda方法体中只有一行创建对象的代码,并且返回值就是该对象
	代码:
		Supplier<Employee> supplier=()->new Employee();
		Supplier<Employee> supplier2=Employee::new;
		
		Employee employee=supplier.get();
		
		class Employee{
            private String name;
            private int money;
            public Employee(String name,int money) {
                this.money = money;
                this.name = name;
            }
            public String getName() {
                return name;
            }
        }

三、Stream

1.简介

  • Stream:流
    与集合类似,但是集合中存储的是数据,而Stream中存储的是对数据的操作过程
  • 如图:
    原料 -> 工序1 -> 工序2 -> 工序n -> 产品
  • 注意:
    1,Stream不会存储数据
    2,Stream不会改变原数据,他们会返回一个持有加工后数据的新Stream
    3,Stream会延迟执行,会等到需要的结果才执行

2.使用步骤

  • 创建:
    新建一个Stream
  • 中间操作:
    在一个或多个步骤中,将初始Stream转换为另一个Stream的中间操作
  • 终止操作:
    使用一个终止操作来产生一个结果,该操作会强制之前的延迟操作立即执行.此后该Stream不能在使用

3.获取Stream

1,通过集合对象(Collection)的stream()或parallelStream()方法

	代码:
		ArrayList<String> arrayList=new ArrayList<>();
		//并行流
		Stream<String> stream = arrayList.parallelStream();ArrayList<String> list = new ArrayList<String>();
		Stream<String> stream = list.stream();

2,通过Arrays工具类的静态stream方法

	代码:
		String[] arr= {"aaa","bbb","ccc"};
		Stream<String> stream2=Arrays.stream(arr);

3,通过Stream接口中的静态of,iterate,generate方法

	代码:of普通流
		Stream<Integer> stream = Stream.of(10,20,30,40,50);
	代码:iterate迭代流
		Stream<Integer> iterate = Stream.iterate(0, x->x+2);
	代码:generate生成流
		Stream<Integer> generate = Stream.generate(()->new Random().nextInt(100));

4,通过IntStream,LongStream,DoubleStream接口的of,range,rangeClosed方法

	代码:
		IntStream stream = IntStream.of(100,200,300);
	代码:
		IntStream range = IntStream.rangeClosed(0, 50);

4.中间操作

1,filter过滤

	代码:
		ArrayList<Employee> list=new ArrayList<>();
		list.add(new Employee("小王", 15000));
		list.add(new Employee("小张", 12000));
		list.add(new Employee("小李", 18000));
		list.add(new Employee("小孙", 20000));
		list.add(new Employee("小刘", 25000));
		list.add(new Employee("小刘", 25000));
		//获取薪资大于15000,forEach终止操作,遍历结果
		list.stream()
			.filter(e->e.getMoney()>15000)
			.forEach(System.out::println);

2,limit限制


	代码:
		ArrayList<Employee> list=new ArrayList<>();
		list.add(new Employee("小王", 15000));
		list.add(new Employee("小张", 12000));
		list.add(new Employee("小李", 18000));
		list.add(new Employee("小孙", 20000));
		list.add(new Employee("小刘", 25000));
		list.add(new Employee("小刘", 25000));
		//获取集合中前两个输出
		list.stream()
			.limit(2)
			.forEach(System.out::println);

3,skip跳过

	代码:
		ArrayList<Employee> list=new ArrayList<>();
		list.add(new Employee("小王", 15000));
		list.add(new Employee("小张", 12000));
		list.add(new Employee("小李", 18000));
		list.add(new Employee("小孙", 20000));
		list.add(new Employee("小刘", 25000));
		list.add(new Employee("小刘", 25000));
		//跳过集合中前两个输出
		list.stream()
		.skip(2)
		.forEach(System.out::println);

4,distinct去掉重复
注意:存储对象必须实现hashCode()和equals()方法,用这两个方法判断是否重复,先调用哪个hashCode方法,如果该方法的返回值与存储其他数据一致,在调用equals比较

	代码:
		ArrayList<Employee> list=new ArrayList<>();
		list.add(new Employee("小王", 15000));
		list.add(new Employee("小张", 12000));
		list.add(new Employee("小李", 18000));
		list.add(new Employee("小孙", 20000));
		list.add(new Employee("小刘", 25000));
		list.add(new Employee("小刘", 25000));
		
		list.stream()
		.distinct()
		.forEach(System.out::println);

5,sorted排序

	代码:
		ArrayList<Employee> list=new ArrayList<>();
		list.add(new Employee("小王", 15000));
		list.add(new Employee("小张", 12000));
		list.add(new Employee("小李", 18000));
		list.add(new Employee("小孙", 20000));
		list.add(new Employee("小刘", 25000));
		list.add(new Employee("小刘", 25000));
		
		list.stream()
		.sorted((e1,e2)->Double.compare(e1.getMoney(), e2.getMoney()))
		.forEach(System.out::println);

6,map映射操作
简介:将当前Stream中的每个元素都映射转换为另一个元素,从而得到一个新的Stream

	代码:	
		ArrayList<Employee> list=new ArrayList<>();
		list.add(new Employee("小王", 15000));
		list.add(new Employee("小张", 12000));
		list.add(new Employee("小李", 18000));
		list.add(new Employee("小孙", 20000));
		list.add(new Employee("小刘", 25000));
		list.add(new Employee("小刘", 25000));
		
		list.stream()
		.map(e->e.getName())
		.forEach(System.out::println);

7,parallel并行流

	简介:采用多线程 效率高
	代码:
		ArrayList<Employee> list=new ArrayList<>();
		list.add(new Employee("小王", 15000));
		list.add(new Employee("小张", 12000));
		list.add(new Employee("小李", 18000));
		list.add(new Employee("小孙", 20000));
		list.add(new Employee("小刘", 25000));
		list.add(new Employee("小刘", 25000));
		
		list.stream().parallel()
		.forEach(System.out::println);

5.终止操作

1,forEach遍历

	代码:
		ArrayList<Employee> list=new ArrayList<>();
		list.add(new Employee("小王", 15000));
		list.add(new Employee("小张", 12000));
		list.add(new Employee("小李", 18000));
		list.add(new Employee("小孙", 20000));
		list.add(new Employee("小刘", 25000));
		list.add(new Employee("小刘", 25000));
		list.stream().forEach(System.out::println);

2,min最小值

	代码:
		ArrayList<Employee> list=new ArrayList<>();
		list.add(new Employee("小王", 15000));
		list.add(new Employee("小张", 12000));
		list.add(new Employee("小李", 18000));
		list.add(new Employee("小孙", 20000));
		list.add(new Employee("小刘", 25000));
		list.add(new Employee("小刘", 25000));
		
		Optional<Employee> min = list.stream().min((o1,o2)->Integer.compare(o1.getMoney(), o2.getMoney()));
		System.out.println(min.get());

3,max最大值

	代码:
		ArrayList<Employee> list=new ArrayList<>();
		list.add(new Employee("小王", 15000));
		list.add(new Employee("小张", 12000));
		list.add(new Employee("小李", 18000));
		list.add(new Employee("小孙", 20000));
		list.add(new Employee("小刘", 25000));
		list.add(new Employee("小刘", 25000));
		
		Optional<Employee> max = list.stream().max((e1,e2)->Integer.compare(e1.getMoney(), e2.getMoney()));
		System.out.println(max.get());

4,count数量


	代码:
		//薪资大于20000的人数
		ArrayList<Employee> list=new ArrayList<>();
		list.add(new Employee("小王", 15000));
		list.add(new Employee("小张", 12000));
		list.add(new Employee("小李", 18000));
		list.add(new Employee("小孙", 20000));
		list.add(new Employee("小刘", 25000));
		list.add(new Employee("小刘", 25000));
		
		long count = list.stream().filter(o -> o.getMoney()>20000).count();
		System.out.println(count);

5,reduce规约

	代码:
		//所有员工薪资和
		ArrayList<Employee> list=new ArrayList<>();
		list.add(new Employee("小王", 15000));
		list.add(new Employee("小张", 12000));
		list.add(new Employee("小李", 18000));
		list.add(new Employee("小孙", 20000));
		list.add(new Employee("小刘", 25000));
		list.add(new Employee("小刘", 25000));
		
		Optional<Double> sum = list.stream()
			.map(e->e.getMoney())
			.reduce((x,y)->x+y);
		System.out.println(sum.get());

6,collect收集

	代码:
		//获取所有的员工姓名,封装成一个list集合
		ArrayList<Employee> list=new ArrayList<>();
		list.add(new Employee("小王", 15000));
		list.add(new Employee("小张", 12000));
		list.add(new Employee("小李", 18000));
		list.add(new Employee("小孙", 20000));
		list.add(new Employee("小刘", 25000));
		list.add(new Employee("小刘", 25000));
		
		List<String> names = list.stream()
			.map(e->e.getName())
			.collect(Collectors.toList());
		for (String string : names) {
			System.out.println(string);
		}

四、新时间API

1. 简介

之前时间API存在线程安全问题,设计混乱,顾重新编写的新时间类

1.验证: 之前jdk提供的时间类,在多线程环境下是不安全的(下面程序会崩溃)

	SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMdd");
		ExecutorService pool = Executors.newFixedThreadPool(10);
		Callable<Date> callable=new Callable<Date>() {
			@Override
			public Date call() throws Exception {
				
				return sdf.parse("20200525");
			}
		};
		List<Future<Date>> list=new ArrayList<>();
		for(int i=0;i<10;i++) {
			Future<Date> future=pool.submit(callable);
			list.add(future);
		}
		
		for (Future<Date> future : list) {
			System.out.println(future.get().toLocaleString());
		}
		pool.shutdown();

2. 新时间API相关类

1.LocalDate 与 LocalDateTime

  • 作用: 代替Date
  • 方法:
    •  now():获取当前时间,静态方法
      
    •  of():获取指定时间,静态方法
      
    •  getYear():获取年
      
    •  getMonthValue():获取月
      
    •  getDayOfMonth():获取日
      
    •  plusXXX():添加
      
    •  minusXXX():减少
      
    •  atZone(ZoneId zoneId):将时间转换为指定时区的时间
      
    •  format(DateTimeFormatter dtf):将时间转换为指定格式的字符串
      
    •  parse(CharSequence text, DateTimeFormatter formatter):将指定格式的字符串转换为时间
      
    代码:
        //1创建本地时间
        LocalDateTime localDateTime=LocalDateTime.now();
        //LocalDateTime localDateTime2=LocalDateTime.of(year, month, dayOfMonth, hour, minute)
        System.out.println(localDateTime);
        System.out.println(localDateTime.getYear());
        System.out.println(localDateTime.getMonthValue());
        System.out.println(localDateTime.getDayOfMonth());

        //2添加两天
        LocalDateTime localDateTime2 = localDateTime.plusDays(2);
        System.out.println(localDateTime2);

        //3减少一个月
        LocalDateTime localDateTime3 = localDateTime.minusMonths(1);
        System.out.println(localDateTime3);

2.DateTimeFormatter

  • 作用: 代替SimpleDateFormat
  • 方法:
    •  ofPattern("时间格式"):设定时间格式
      
    代码:
    	DateTimeFormatter dtf=DateTimeFormatter.ofPattern("yyyyMMdd");
    	ExecutorService pool = Executors.newFixedThreadPool(10);
    	Callable<LocalDate> callable=new Callable<LocalDate>() {
    		@Override
    		public LocalDate call() throws Exception {
    			return LocalDate.parse("20200525",dtf);
    		}
    	};
    	List<Future<LocalDate>> list=new ArrayList<>();
    	for(int i=0;i<10;i++) {
    		Future<LocalDate> future=pool.submit(callable);
    		list.add(future);
    	}
    	for (Future<LocalDate> future : list) {
    		System.out.println(future.get());
    	}
    	pool.shutdown();

3.ZoneId:时区

	方法:
		public static Set<String> getAvailableZoneIds():获取所有时区
		public static ZoneId systemDefault():获取系统默认时区

4.Instant:时间戳

	方法:
		public static Instant now():获取当前时间
		public long toEpochMilli():获取当前时间与19701100:00:00:000的时间差,单位毫秒
		public Instant plusSeconds(long secondsToAdd):减数当前时间的秒数

5.时间转换:

(1) Date —>Instant---->LocalDateTime

	代码:
        Date date=new Date();
        Instant instant = date.toInstant();			
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());	

(2) LocalDateTime —>Instant---->Date

    代码:
    	Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
		Date from = Date.from(instant);
		System.out.println(from);
		
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值