Java 8 新特性总结

Java8特性

1.Java8概述

  • Java(JDK1.8)是Java语言开发的一个主要版本
    • 支持Lambda表达式
    • 函数式接口
    • 新的StreamAPI
    • 新的日期API
    • 其他特性

2.Lambda表达式

  • Lambda表达式:特殊的匿名内部类,语言更简洁

  • Lambda表达式允许把函数作为一个方法的参数(函数作为方法参数传递),将代码像数据一样传递

  • 基本语法:

    <函数式接口><变量名>=(参数1,参数2…)->{//方法体};

Lambda Demo
public static void main(String[] args) {
        //匿名内部类对象
        Runnable runnable=new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"is executor.");
            }
        };

        //Lambda优化匿名内部类,
        Runnable runnable1=()->{
            System.out.println(Thread.currentThread().getName()+"is executor.");
        };
        //Lambda表达式中只有一条语句,省略方法的{}.
        Runnable runnable2=()-> System.out.println(Thread.currentThread().getName()+"is executor.");

        new Thread(runnable).start();
        new Thread(runnable1).start();
        new Thread(runnable2).start();

        Comparator<String>comparator=new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.compareTo(o2);
            }
        };
        //Lambda优化
        Comparator<String>comparator1=(String o1,String o2)->{
            return o1.compareTo(o2);
        };
        
        //Lambda表达式中只有一条语句,省略方法的{},如果有返回值 return省略
        Comparator<String>comparator2=(String o1,String o2)->o1.compareTo(o2);
        
        //参数中类型可以推断出来,可以省略
        Comparator<String>comparator3=(o1,o2)->o1.compareTo(o2);
        
        //方法引用简化
        Comparator<String>comparator4=String::compareTo;
    }
  • Lambda引入了引得操作符:->(箭头操作符),->将表达式分成两部分
    • 左侧:(参数1,参数2.。)表示参数列表
    • 右侧:{}内不是方法体
  • 注意事项
    • 形参列表的数据类型会自动推断
    • 如果形参列表为空,只需保留();
    • 如果形参只有1个,()可以省略,只需要参数的名称即可。
    • 如果执行语句只有一句,且无返回值,{}可以省略,若有返回值,则若想去{},则必须同时省略return,且执行语句也保证只有一句。
    • Lambda不会生成一个单独的内部类。

3.函数式接口

  • 如果一个接口只有一个抽象方法,则该接口称之为函数式接口,函数式接口可以使用Lambda表达式,Lambda表达式会被匹配到这个抽象方法上。
  • @FunctionInterface 注解检测接口是否符合函数式接口。
//MyPredicate.java
@FunctionalInterface
public interface MyPredicate<T> {
    public abstract boolean test(T t);
}
//Usb.java
@FunctionalInterface
public interface Usb {
    public abstract void work();
}
//Main.java
public static void main(String[] args) {
        Usb usb = new Usb() {
            @Override
            public void work() {
                System.out.println("usb begin work.");
            }
        };
        Usb usb1 = () -> System.out.println("usb begin work.");

        MyPredicate<String> myPredicate = new MyPredicate<String>() {
            @Override
            public boolean test(String s) {
                if (s.startsWith("H")) {
                    return true;
                }
                return false;
            }
        };

        MyPredicate<String> myPredicate1 = s -> {
            if (s.startsWith("H")) {
                return true;
            }
            return false;
        };
    }
常用函数式接口
函数式接口参数类型返回类型说明
Consumer消费型接口Tvoidvoid accpet(T t);对类型为T的对象应用操作
Supplier供给型接口TT get();返回类型为T的对象
Function<T,R>函数型接口TRRapply(T t);对类型为T的对象应用操作,并返回类型为R类型的对象。
Predicate断言型接口Tbooleanboolean test(T t);确定类型为T的对象是否满足条件,并返回boolean类型
public class Main {
    public static void main(String[] args) {
        /**
         * 演示函数式接口的使用
         * Consumer 消费型
         * Supplier 供给型
         * Function 函数型
         * Predicate   断言型
         */

        happy(new Consumer<Double>() {
            @Override
            public void accept(Double d) {
                System.out.println("attend a party , and cast " + d);
            }
        }, 1000);

        happy(d -> System.out.println("attend a part, and cast " + d), 1000);
        happy(d -> System.out.println("and to waste a foot " + d), 2000);


        int[] nums = getNums(() -> new Random().nextInt(100), 5);
        System.out.println(Arrays.toString(nums));


        String result = handlerString(s -> s.toUpperCase(), "hello");
        System.out.println(result);

        String result2 = handlerString(s -> s.trim(), "java  pthron   ");
        System.out.println(result2);


        ArrayList<String> names = new ArrayList<>();
        names.add("张三");
        names.add("张无忌");
        names.add("赵敏");
        ArrayList<String> result3 = filter(s -> s.startsWith("张"), names);
        System.out.println(result3);
    }

    //Consumer  消费型
    public static void happy(Consumer<Double> consumer, double money) {
        consumer.accept(money);
    }

    //Supplier  供给型
    public static int[] getNums(Supplier<Integer> supplier, int length) {
        int[] arr = new int[length];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = supplier.get();
        }
        return arr;
    }

    //Function  函数型
    public static String handlerString(Function<String, String> function, String str) {
        String apply = function.apply(str);
        return apply;
    }

    //Predicate  断言型
    public static ArrayList<String> filter(Predicate<String> predicate, ArrayList<String> names) {
        ArrayList<String> list = new ArrayList<>();
        for (String s : names) {
            if (predicate.test(s)) {
                list.add(s);
            }
        }
        return list;
    }
}

4.方法引用

  • 方法引用是Lambda表达式的一种简写形式。如果Lambda表达式方法体中。只是调用一种特定的已经存在的方法,则可以使用方法引用。
  • 常见形式
    • 对象::实例方法
    • 类::静态方法
    • 类:: 实例方法
    • 类::new
public class Main {
    public static void main(String[] args) {

        //1.对象::实例方法
        //消费型接口
        // 1)Lambda中只调用了一个方法 System.out.println()方法
        // 2)调用方法的形式(参数和返回值)和接口一样
        Consumer<String> consumer = s -> System.out.println(s);
        //使用方法引用优化,提供新的操作符::
        Consumer<String> consumer1 = System.out::println;
        consumer1.accept("hello");

        //类::静态方法
        //1)Lambda中只调用一个方法,2)调用方法compare的形式(参数和返回值)和接口一样
//        Comparator<Integer>comparator=(o1,o2)->{
//            return Integer.compare(o1, o2);
//        };
        Comparator<Integer> comparator = (o1, o2) -> Integer.compare(o1, o2);
        Comparator<Integer>comparator=Integer::compare;

        //类::实例方法
        //1)Lambda中只调用一个方法  2)有一个参数作为Lambda中方法的调用者,其他作为参数传递
        Comparator<String> comparator2 = (o1, o2) -> o1.compareTo(o2);
        Comparator<String> comparator3 = String::compareTo;

        //Employee.java
        //1)Lambda中只调用一个方法  2)有一个参数作为Lambda中方法的调用者,其他作为参数传递
        Function<Employee, String> function = e -> e.getName();
        Function<Employee, String> function1 = Employee::getName;
        System.out.println(function.apply(new Employee()));

        //类::new
        //1)Lambda中只调用用一个构造方法 2)构造方法中的参数和接口中的参数一样
        Supplier<Employee> supplier = () -> new Employee();
        Supplier<Employee> supplier1 = Employee::new;

        MySupplier<Employee> supplier2 = (n, a, s) -> new Employee(n, a, s);
        MySupplier<Employee> supplier3 = Employee::new;
        System.out.println(supplier3.get("dmeodong", 12, 12.0));

        //数组
        //元素类型[]::new
        // 1) Lambda中只创建数组 2)参数作为数组的长度
        Function<Integer,int[]>function2=n->new int[n];
        Function<Integer,int[]>function3=int[]::new;
        int[] apply = function3.apply(4);
    }
}
//MySupplier.java
public interface MySupplier <T>{
    T get(String name,int age,double salary);
}
  • 问题1:上面Systme.out.println()为什么可以使用方法引用
//消费类型只有参数而无返回值
//查看System.out的源码发现out是一个PrintStream类,
public final static PrintStream out = null;
//而且PrintStream实现了println(String s)方法且无返回值,
public void println(String x) {
    synchronized (this) {
        print(x);
        newLine();
    }
}
//所以是同类型的可以实现
//突然看了一下Integer的源码发现Integer只实现了Comparable接口并没有实现Comparator接口,为什么有
//compare方法,还真有,Integer自己写的
public static int compare(int x, int y) {
        return (x < y) ? -1 : ((x == y) ? 0 : 1);
    }

  • 一般类排序都会实现 Comparable接口中的compareTo方法
  • 比较器是Comparator接口实现compare方法
  • 如果想改变排序规则Cpmarator的优先级比Comparable的高。

Comparator 和 Comparable 比较

Comparable是排序接口;若一个类实现了Comparable接口,就意味着“该类支持排序”。
而Comparator是比较器;我们若需要控制某个类的次序,可以建立一个“该类的比较器”来进行排序。

我们不难发现:Comparable相当于“内部比较器”,而Comparator相当于“外部比较器”。

5.Stream API

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

  • Stream特点

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

    • 创建
      • 新建一个流
    • 中间操作:
      • 在一个或多个步骤中,将初始Stream转化到另一个Stream的中间操作。
    • 终止操作:
      • 是一个终止操作来产生一个结果。该操作会强制之前的延迟操作立即执行,再次之后,该Stream就不能使用了,
  • 创建Stream

    • 通过Collection对象的stream()或parallelStream(方法。 并行
    • 通过Arrays类的stream()方法。
    • 通过Stream接口的of(). iterate(). generate(方法。
    • 通过IntStream. LongStream. DoubleStream接口中的of、 range.
      rangeClosed方法。
public static void main(String[] args) {
        //1)创建流
        //1.1通过Collection或parallelStream()方法
        ArrayList<String> list = new ArrayList<>();
        list.add("waterlemon");
        list.add("peach");
        list.add("banana");
        list.add("apple");
        //获取串行流(单线程)
        //        Stream<String> stream = list.stream();
//        stream.forEach(s -> System.out.println(s));
        //获取并行流(多线程)
        Stream<String> stream = list.parallelStream();
        stream.forEach(System.out::println);
        //1.2通过Arrays类的stream()方法。
        IntStream stream1 = Arrays.stream(new int[]{1, 2, 8, 4, 6});
        stream1.sorted().forEach(System.out::println);
        //1.3通过Stream类接口的of(),iterate(),generate()方法
        Stream<String> stream2 = Stream.of(new String[]{"北京", "南京", "huoche"});
        stream2.filter(s -> s.endsWith("京")).forEach(System.out::println);

        //无限迭代流
        Stream<Integer> iterate = Stream.iterate(0, x -> x + 2);
        iterate.limit(100).forEach(System.out::println);

        //无限生成流
        Stream<Integer> generate = Stream.generate(() -> new Random().nextInt(100));
        generate.limit(10).forEach(System.out::println);

        //1.4通过IntStream,LongStream,DoubleStream接口中的of,range,reangeClosed方法
        IntStream intStream = IntStream.of(new int[]{10, 2, 30, 4});
        intStream.forEach(System.out::println);
        IntStream range = IntStream.range(0, 100);
        range.forEach(System.out::println);
        IntStream intStream1 = IntStream.rangeClosed(0, 100);
        intStream1.forEach(System.out::println);
    }
中间操作,终止操作
  • 中间操作
    • filter,limit,skip,distinct,sorted
    • map
    • parallel
  • 终止操作
    • forEach,min,max,count
    • reduce,collect
 public static void main(String[] args) {
        //集合
        ArrayList<Employee> employees = new ArrayList<>();
        employees.add(new Employee("demodong1", 18, 2000));
        employees.add(new Employee("demodong2", 15, 100000));
        employees.add(new Employee("demodong3", 12, 20000900));
        employees.add(new Employee("demodong4", 10, 20));
        employees.add(new Employee("demodong5", 10, 20));
        //filter过滤
        employees.stream()
                .filter(x -> x.getAge() > 15)
                .forEach(System.out::println);
        employees.stream()
                .filter(s -> s.getSalary() > 5000)
                .forEach(System.out::println);

        //limit 限制数据个数
        employees.stream()
                .limit(2)
                .forEach(System.out::println);

        //skip  逃过n个元素
        employees.stream()
                .skip(2)
                .forEach(System.out::println);

        //distinct  去掉重复的 hashCode和equals
        employees.stream()
                .distinct()
                .forEach(System.out::println);


        //sorted  排序
        employees.stream()
                .sorted((o1, o2) -> Double.compare(o1.getSalary(), o2.getSalary()))
                .forEach(System.out::println);
    }

在这里插入图片描述

在这里插入图片描述

public static void main(String[] args) {
        ArrayList<Employee> employees = new ArrayList<>();
        employees.add(new Employee("dmeodong1", 12, 200));
        employees.add(new Employee("dmeodong2", 13, 200));
        employees.add(new Employee("dmeodong3", 12, 500));
        employees.add(new Employee("dmeodong4", 121, 400));
        employees.add(new Employee("dmeodong5", 19, 300));
        employees.add(new Employee("dmeodong6", 10, 100));
        //map 映射
        //获取所有人都姓名
        employees.stream()
                .map(Employee::getName)
                .forEach(System.out::println);
        //parallel 并行流
        employees.stream()
                .filter(s -> s.getAge() > 10)
                .sorted(((o1, o2) -> Double.compare(o1.getSalary(), o2.getSalary())))
                .distinct()
                .forEach(System.out::println);

        //min max count
        //Options是一个元素容易,防止空指针异常
        Optional<Employee> min = employees.stream()
                .min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
        System.out.println(min.get());
        Optional<Employee> max = employees.stream()
                .max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
        System.out.println(max.get());
        Optional<Employee> count = employees.stream()
                .min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
        System.out.println(count);


        //reduce ,collect
        //reduce:规约,统计
        Optional<Integer> reduce = employees.stream()
                .map(e1 -> (int) e1.getSalary())
                .reduce((x, y) -> x + y);
        System.out.println(reduce);

        //collect:收集
        //收集所有人的姓名
        List<String> collect = employees.stream()
                .map(e -> e.getName())
                .collect(Collectors.toList());
        System.out.println(collect.toString());

        //平均工资
        Double collect1 = employees.stream()
                .map(e -> e.getSalary())
                .collect(Collectors.averagingDouble(s -> s));
        System.out.println(collect1);
    }

6.新时间API

  • 本地化日期时间 API:
    • LocalDate
    • LocalTime
    • LocalDateTime
  • Instant:时间戳
  • Zoneld:时区
  • Date,Instant.LocalDateTime的转换
  • DateTimeFormatter:格式化类
    public static void main(String[] args) {
        //创建本地日期和时间
        LocalDateTime localDateTime = LocalDateTime.now();
        System.out.println(localDateTime.getYear());
        System.out.println(localDateTime.getMonth().getValue());
        System.out.println(localDateTime.getDayOfMonth());
        System.out.println(localDateTime.getHour());
        System.out.println(localDateTime.getMinute());
        System.out.println(localDateTime.getSecond());

        //昨天
        LocalDateTime yesterday = localDateTime.minusDays(1);

        //明天
        LocalDateTime tomorrow = LocalDateTime.of(2020, 8, 14, 10, 13, 13);
		//本月第几天
        LocalDateTime localDateTime1 = localDateTime.withDayOfMonth(10);

        System.out.println(localDateTime1);
    }
    //instant:时刻,瞬间: 从1970年1月1日0:0:0
        Instant instant = Instant.now();
        System.out.println("second" + instant.getEpochSecond());
        System.out.println("millssecond" + instant.toEpochMilli());

        //昨天
        Instant yesterday = instant.minusMillis(24 * 60 * 60 * 1000);

        //明天
        Instant tomorrow = instant.plus(1, ChronoUnit.DAYS);

        System.out.println(instant);
        System.out.println(yesterday);
        System.out.println(tomorrow);

//        System.out.println(instant.get(ChronoField.YEAR_OF_ERA));
//        System.out.println(instant.get(ChronoField.MONTH_OF_YEAR));
//        System.out.println(instant.get(ChronoField.DAY_OF_MONTH));

        //Date
        //Date --> Instant  ---> LocalDateTime
        Date date = new Date();
        Instant instant1 = date.toInstant();
        System.out.println(date);
        System.out.println(instant1);

        //时区  ZoneId
        System.out.println(ZoneId.systemDefault());
        Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
        for (String availableZoneId : availableZoneIds) {
            System.out.println(availableZoneId);
        }
        LocalDateTime localDateTime = instant1.atZone(ZoneId.systemDefault()).toLocalDateTime();
        
        //LocalDateTime ->instance ->Date
        Instant instant2 = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
        Date date1 = Date.from(instant2);
   //创建时间格式化器
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        //把日期改为字符串
        LocalDateTime now = LocalDateTime.now();
        String format = dtf.format(now);
        System.out.println(format);

        //字符串改为日期
        LocalDateTime parse = LocalDateTime.parse("2020-08-13 17:24:00",dtf);
        System.out.println(parse);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值