JAVA8新特性、Lambda表达式、函数式接口、方法引用、Stream、时间API(JAVA基础十五)

一、Java8概述

Java8 (又称 JKD1.8) 是 Java 语言开发的一个主要版本。
Oracle公司于2014年3月18日发布Java8 。

  • 支持Lambda表达式
  • 函数式接口
  • 新的Stream API
  • 新的日期 API
  • 其他特性

二、Lambda表达式

2.1 概念

  • Lambda表达式是特殊的匿名内部类,语法更简洁。
  • Lambda表达式允许把函数作为一个方法的参数(函数作为方法参数传递),将代码像数据一样传递。

2.2 语法

<函数式接口> <变量名> = (x {]()
​ //方法体

[};

2.3 基本使用

演示案例:

package com.qfedu.jdk8new;

import java.util.Comparator;

public class Test01 {
    
    
    public static void main(String[] args) {
    
    

        //1.匿名内部类,定义runnable
        Runnable runnable = new Runnable() {
    
    
            @Override
            public void run() {
    
    
                System.out.println("3333");
            }
        };

        //不带参数的简化
        Runnable runnable1 = () -> {
    
    
            System.out.println("3333");
        };

        Comparator<Integer> comparator = new Comparator<Integer>() {
    
    
            @Override
            public int compare(Integer o1, Integer o2) {
    
    
                return 0;
            }
        };

        //带参数的简化 a,b 形参名,可以自由写
        Comparator<Integer> comparator1 = (a,b)->{
    
    
            return 0;
        };
    }
}

Lambda引入了新的操作符:->(箭头操作符),->将表达式分成两部分:

  • 左侧:(参数1,参数2…)表示参数列表
  • 右侧:{ }内部是方法体

注意事项:

2.4 案例

Usb接口:

@FunctionalInterface
public interface Usb {
    
    
	void service();
}

TestUsb类:

public class TestUsb {
    
    
	public static void main(String[] args) {
    
    
		//匿名内部类
		Usb mouse=new Usb() {
    
    
			
			@Override
			public void service() {
    
    
				System.out.println("鼠标开始工作了..........");
			}
		};
		
		Usb fan=()->System.out.println("风扇开始工作了..........");
		
		
		run(mouse);
		run(fan);
	}
	public static void run(Usb usb) {
    
    
		usb.service();
	}
}

三、函数式接口

3.1 概念

  • 如果一个接口只有一个抽象方法,则该接口称之为函数式接口。
  • 函数式接口可以使用Lambda表达式,Lambda表达式会被匹配到这个抽象方法上 。
    • @FunctionalInterface 注解检测接口是否符合函数式接口规范。

3.2 常见函数式接口

接口 参数类型 返回类型 说明
Consumer< T > 消费型接口 T void void accept(T t);对类型为T的对象应用操作
Supplier< T > 供给型接口 T T get(); 返回类型为T的对象
Function< T,R > 函数型接口 T R R apply(T t);对类型为T的对象应用操作,并返回类型为R类型的对象。
Predicate< T > 断言型接口 T boolean boolean test(T t);确定类型为T的对象是否满足条件,并返回boolean类型。

案例演示:

扫描二维码关注公众号,回复: 14673302 查看本文章
package com.qfedu.jdk8new;

import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

public class Test02 {
    
    

    public static void main(String[] args) {
    
    

        //1限定了一个接口中只有一个方法

        //2.  一个参数 和返回值
        //   有参数 没有返回值
        Consumer<String> consumer = new Consumer<String>() {
    
    
            @Override
            public void accept(String s) {
    
    
                System.out.println(s);
            }
        };
        Consumer<String> consumer1 = (s) ->{
    
    
            System.out.println(s);
        };

        consumer1.accept("ooooo");

        //   没有参数 有返回值
        Supplier<String>  supplier = new Supplier<String>() {
    
    
            @Override
            public String get() {
    
    
                return "哈哈";
            }
        };
        System.out.println(supplier.get());

        //   有参数  有返回值
        Function<String,String>  function = new Function<String, String>() {
    
    
            @Override
            public String apply(String s) {
    
    
                return s+"123";
            }
        };
        Function<String,String>  function1 = (a) -> {
    
    
            return a+"123";
        };

        System.out.println(function1.apply("555"));

        Predicate<String> predicate = new Predicate<String>() {
    
    
            @Override
            public boolean test(String str) {
    
    
                if(str==null || str.length()<=0) {
    
    
                    return  false;
                }
                return true;
            }
        };
        Predicate<String> predicate1 = (str) -> {
    
    
            if(str==null || str.length()<=0) {
    
    
                return  false;
            }
            return true;
        };
    }
}

四、方法引用

4.1 概念

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

常见形式:

  • 对象::实例方法
  • 类::静态方法
  • 类::实例方法
  • 类::new

4.2 基本使用

Hero类:

package com.qfedu.jdk8x;

public class Hero {
    
    

    private  Integer id;
    private  String name;

    public Hero() {
    
    
    }

    public Hero(Integer id, String name) {
    
    
        this.id = id;
        this.name = name;
    }

    public Integer getId() {
    
    
        return id;
    }

    public void setId(Integer id) {
    
    
        this.id = id;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    @Override
    public String toString() {
    
    
        return "Hero{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

Test3类:

package com.qfedu.jdk8new;

import java.util.function.Consumer;
import java.util.function.Supplier;

public class Test03 {
    
    

    public static void main(String[] args) {
    
    

//               + 对象::实例方法
        Consumer<String> consumer = new Consumer<String>() {
    
    
            @Override
            public void accept(String s) {
    
    
                System.out.println(s);
            }
        };

        Consumer<String> consumer1 = (s) -> {
    
    
           // System.out.println(s);
            Hero hero = new Hero();
            hero.setName(s);
        };

        Hero hero = new Hero();
        Consumer<String> consumer2 = hero::setName;
//                + 类::静态方法
        Consumer<String> consumer3 =Hero::add;
        consumer3.accept("asss");
//                + 类::实例方法( 必须 一个地方传入对象)
        Consumer<Hero> consumer4 = new Consumer<Hero>() {
    
    
            @Override
            public void accept(Hero hero) {
    
    
                hero.getId();
            }
        };
        Consumer<Hero> consumer5 =Hero::getId;
        consumer5.accept(new Hero());
//                + 类::new 用来返回一个对象   Hero:new    Hero h = new Hero();
        Supplier<Hero> supplier = new Supplier<Hero>() {
    
    
            @Override
            public Hero get() {
    
    
                return new Hero();
            }
        };
        Supplier<Hero> supplier1 = () -> {
    
    

            return  new Hero();
        };

        Supplier<Hero> supplier2 = Hero::new;
        Hero hero1 = supplier2.get();
    }
}

五、Stream

5.1 概念

流(Stream)与集合类似,但集合中保存的是数据,而Stream中保存对集合或数组数据的操作。

在这里插入图片描述

5.2 Stream特点

  • Stream 自己不会存储元素。
  • Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
  • Stream 操作是延迟执行的,会等到需要结果的时候才执行。

5.3 Stream使用步骤

创建:

  • 新建一个流。

中间操作:

  • 在一个或多个步骤中,将初始Stream转化到另一个Stream的中间操作。

终止操作:

  • 使用一个终止操作来产生一个结果。该操作会强制之前的延迟操作立即执行,在此之后,该Stream就不能使用了。

5.4 创建Stream

  • 通过Collection对象的stream()或parallelStream()方法。
  • 通过Arrays类的stream()方法。
  • 通过Stream接口的of()、iterate()、generate()方法。
  • 通过IntStream、LongStream、DoubleStream接口中的of、range、rangeClosed方法。

案例演示:

package com.qfedu.jdk8new;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.IntStream;
import java.util.stream.Stream;

//Stream操作1: 获取Stream对象

public class Test04 {
    
    

    public static void main(String[] args) {
    
    

        //1.准备一个集合
        List<Hero>  heroList = new LinkedList<>();
        heroList.add(new Hero(1001,"小乔"));
        heroList.add(new Hero(1002,"大乔"));
        heroList.add(new Hero(1003,"老乔"));
        heroList.add(new Hero(1004,"二乔"));
        heroList.add(new Hero(1005,"三乔"));

        System.out.println(heroList);

        System.out.println("==================================");
        //获取流
        Stream<Hero> stream = heroList.stream();
/*        Consumer<Hero> comsumer = (hero) ->{
            System.out.println(hero);
        };*/
        Consumer<Hero> comsumer = System.out::println;
        stream.forEach(comsumer);

        String[] strings = {
    
    "123","456","789","010"};
        Stream<String> stream1 = Arrays.stream(strings);

        System.out.println("====== 利用Arrays.stream");
        Consumer<String> comsumer1  = new Consumer<String>() {
    
    
            @Override
            public void accept(String s) {
    
    
                System.out.println(s);
            }
        };
        stream1.forEach(comsumer1);

        System.out.println("=========通过of方法");  // 通过Stream接口的of()、iterate()、generate()方法。
        Stream<Integer> integerStream = Stream.of(1, 2, 3);
        integerStream.forEach(System.out::println);

        System.out.println("===================of");
        //        + 通过IntStream、LongStream、DoubleStream接口中的of、range、rangeClosed方法。
        IntStream intStream = IntStream.of(1, 2, 3, 4);
        intStream.forEach(System.out::println);
    }
}

5.5 中间操作

常见中间操作:

  • filter、limit、skip、distinct、sorted
  • map
  • parallel

案例演示:

package com.qfedu.jdk8x;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class Test5 {
    
    

    public static void main(String[] args) {
    
    

        //1.创建集合
        List<Hero>  heroList = new ArrayList<>();

        //2. 添加一些数据
        heroList.add(new Hero(1009,"小乔"));
        heroList.add(new Hero(1002,"大乔"));
        heroList.add(new Hero(1003,"老乔"));
        heroList.add(new Hero(1004,"女乔"));

        System.out.println(heroList);

        // + 通过Collection对象的stream()或parallelStream()方法。

        Stream<Hero> stream = heroList.stream();

        //(1) filter过滤  过滤掉哪些元素: 如果过滤出来 ,返回true
        System.out.println("------filter-------");
        Predicate<Hero> predicate = new Predicate<Hero>() {
    
    
            @Override
            public boolean test(Hero hero) {
    
    

                if(hero.getId()==1001) {
    
    
                    return  true;
                }
                return false;
            }
        };
        //过滤完成后,返回新的stream
        stream.filter(predicate).forEach(System.out::println);

        System.out.println("原来的"+heroList);

        //(2) limit限制
        System.out.println("----limit------");
        heroList.stream().limit(2).forEach(System.out::println);

        //(3) skip跳过
        System.out.println("-----skip------");
        heroList.stream().skip(2).forEach(System.out::println);

        System.out.println("---------sorted---------");
        //(4) sorted排序
        Comparator<Hero> b = new Comparator<Hero>() {
    
    
            @Override
            public int compare(Hero o1, Hero o2) {
    
    

                return Integer.compare(o1.getId(),o2.getId());
            }
        };
        heroList.stream().sorted(b).forEach(System.out::println);


        //中间操作2 map
        System.out.println("---------map--------");
/*        Function<Hero,String> cc = new Function<Hero, String>() {
            @Override
            public String apply(Hero hero) {
                return hero.getName();
            }
        };
        */

        Function<Hero,String> cc =  (hero) -> {
    
    
            return  hero.getName();
        };

        heroList.stream()
                .map(cc).forEach(System.out::println);

        //中间操作3 parallel 采用多线程 效率高
        System.out.println("---------map--------");
        heroList.parallelStream()
                .forEach(System.out::println);
    }
}

串行流和并行流:

  • 串行流使用单线程。
  • 并行流使用多线程,效率更高。
public class Demo7 {
    
    
	public static void main(String[] args) {
    
    
		//串行流和并行流的区别
		ArrayList<String> list=new ArrayList<>();
		for(int i=0;i<5000000;i++) {
    
    
			list.add(UUID.randomUUID().toString());
		}
		//串行:10秒  并行:7秒
		long start=System.currentTimeMillis();
        long count=list.Stream().sorted().count();
		//long count=list.parallelStream().sorted().count();
		System.out.println(count);
		long end=System.currentTimeMillis();
		System.out.println("用时:"+(end-start));
	}
}

5.6 终止操作

常见终止操作:

  • forEach、min、max、count
  • reduce、collect

案例演示:

package com.qfedu.jdk8x;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.function.BinaryOperator;
import java.util.stream.Collectors;

public class Test7 {
    
    

    public static void main(String[] args) {
    
    

        //1.创建集合
        List<Hero> heroList = new ArrayList<>();

        //2. 添加一些数据
        heroList.add(new Hero(1009,"小乔"));
        heroList.add(new Hero(1002,"大乔"));
        heroList.add(new Hero(1003,"老乔"));
        heroList.add(new Hero(1004,"女乔"));

        //1 终止操作 foreach
        heroList.stream().forEach(System.out::println);

        //2 终止操作 min max count
        System.out.println("====================");
        Comparator<Hero> cc = new Comparator<Hero>() {
    
    
            @Override
            public int compare(Hero o1, Hero o2) {
    
    
                return Integer.compare(o1.getId(),o2.getId());
            }
        };

        Optional<Hero> min = heroList.stream().min((o1, o2) -> Integer.compare(o1.getId(), o2.getId()));
        System.out.println(min.get());

        Optional<Hero> max = heroList.stream().max((o1, o2) -> Integer.compare(o1.getId(), o2.getId()));
        System.out.println(max.get());

        System.out.println(heroList.stream().count());

        //		//3 终止操作 reduce 规约  计算id的所有和
        //		System.out.println("--------reduce---------");

        BinaryOperator<Integer> aa = new BinaryOperator<Integer>() {
    
    
            @Override
            public Integer apply(Integer integer, Integer integer2) {
    
    
                return integer+integer2;
            }
        };
        Optional<Integer> reduce = heroList.stream().map(hero -> hero.getId()).reduce(aa);

        System.out.println(reduce.get());


        //4 终止方法 collect收集
        //获取所有的员工姓名,封装成一个list集合
        System.out.println("------collect------");
        List<String> collect = heroList.stream().map(hero -> hero.getName()).collect(Collectors.toList());
        System.out.println(collect);
    }
}

六、新时间API

6.1 概述

之前时间API存在问题:线程安全问题、设计混乱。

本地化日期时间 API:

  • LocalDate
  • LocalTime
  • LocalDateTime

Instant:时间戳。

ZoneId:时区。

Date、Instant、LocalDateTime的转换。

DateTimeFormatter:格式化类。

6.2 LocalDateTime类

表示本地日期时间,没有时区信息

public class Demo2 {
    
    
	public static void main(String[] args) {
    
    
		//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);
	}
}

6.3 Instant、ZoneId类

Instant表示瞬间;和前面Date类似。

ZoneId表示时区信息。

public class Demo3 {
    
    
	public static void main(String[] args) {
    
    
		//1 创建Instant:时间戳
		Instant instant=Instant.now();
		System.out.println(instant.toString());
		System.out.println(instant.toEpochMilli());
		System.out.println(System.currentTimeMillis());
		//2 添加减少时间
		Instant instant2 = instant.plusSeconds(10);
        
		System.out.println(Duration.between(instant, instant2).toMillis());
		
		//3ZoneId
		Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
		for (String string : availableZoneIds) {
    
    
			System.out.println(string);
		}
		
		System.out.println(ZoneId.systemDefault().toString());
		
		//1 Date --->Instant--->LocalDateTime
		System.out.println("-------------Date --->Instant---->LocalDateTime-----------");
		Date date=new Date();
		Instant instant3 = date.toInstant();
		System.out.println(instant3);
		
		LocalDateTime localDateTime = LocalDateTime.ofInstant(instant3, ZoneId.systemDefault());
		System.out.println(localDateTime);
		
		//2 LocalDateTime --->Instant--->Date
		System.out.println("-------------LocalDateTime --->Instant---->Date-----------");
	
		Instant instant4 = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
		System.out.println(instant4);
		Date from = Date.from(instant4);
		System.out.println(from);
		
	}
}

6.4 DateTimeFormatter类(会用)

DateTimeFormatter是时间格式化类。

public class Demo4 {
    
    
	public static void main(String[] args) {
    
    
		//创建DateTimeFormatter
		DateTimeFormatter dtf=DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
		//1 把时间格式化成字符串
		String format = dtf.format(LocalDateTime.now());
		System.out.println(format);
		//2 把字符串解析成时间
		LocalDateTime localDateTime = LocalDateTime.parse("2020/03/10 10:20:35", dtf);
		System.out.println(localDateTime);
	}
}

猜你喜欢

转载自blog.csdn.net/LCHONSEONE/article/details/127874788