Concentrated java8 new features Essentials

A, Lambda

1. Define / design reasons

The official explanation: Allows the function as a parameter to a method. So that the code becomes more simple and compact. Expression eliminates the trouble of using anonymous methods.
Personal interpretation: to create an anonymous method

2. Structure

Lambda expressions may be a comma-separated list of parameters, -> sign statements and blocks

  • Optional type declaration: do not need to declare the parameter type, the compiler can be unified identification parameter value.
  • The optional parameters in parentheses: no need to define a parameter in parentheses, but a number of parameters need to be defined parentheses.
  • Optional braces: If the subject is only one sentence, you do not need to use braces.
  • Optional return keyword: If the subject is only one expression that returns a value, the compiler will automatically return value, braces must specify the return value

3, the rules

Local variables used in the expression or not final, will be turned into final, after the code can not change it. Global variables are not limited.

4, using


public class Java8Tester {
    public static void main(String args[]){
        //老版本写法
        MathOperation oldAdd = new MathOperation() {
            @Override
            public int operation(int a, int b) {
                return a+b;
            }
        };

        // jdk8类型声明
        MathOperation addition = (int a, int b) -> a + b;

        // 不用类型声明
        MathOperation subtraction = (a, b) -> a - b;

        // 大括号中的返回语句
        MathOperation multiplication = (int a, int b) -> { return a * b; };

        // 没有大括号及返回语句
        MathOperation division = (int a, int b) -> a / b;

        // 不用括号
        GreetingService greetService1 = message ->
                System.out.println("Hello " + message);

        // 用括号
        GreetingService greetService2 = (message) ->
                System.out.println("Hello " + message);

        greetService1.sayMessage("Runoob");
        greetService2.sayMessage("Google");
    }
    
    @FunctionalInterface
    interface MathOperation {
        int operation(int a, int b);

    }
    
    @FunctionalInterface
    interface GreetingService {
        void sayMessage(String message);
    }
}

Second, the function interface

1. Definitions

The official explanation: function interface (Functional Interface) is a one and only one abstract method, but you can have multiple non-abstract methods of the interface. Interface function can be implicitly converted to lambda expressions and method references.
@FunctionalInterface, for compiling level error checking, with the comment, when you write the interface does not meet the functional interface definition, the compiler will complain.

2, for design reasons

lambda syntax can only function interface, to facilitate the check function interface, @FunctionalInterface to this comment

3, using

@FunctionalInterfaceinterface 
GreetingService {
    void sayMessage(String message);
}
//使用Lambda表达式来表示该接口的一个实现
GreetingService greetService1 = message -> System.out.println("Hello " + message);

Third, the reference method

1. Define / design reasons

The official explanation: The name of the method to point to a method. Configuration can be made more compact and simple language, reducing redundant code.
Personal interpretation: reference method is a more concise and understandable Lambda expressions. The method of direct access or a class or instance constructor.

2, using

Create interfaces and classes

 //函数式接口
@FunctionalInterface
public interface Supplier<T> {
    T get();
}

class Car {

    public static Car create(final Supplier<Car> supplier) {
        return supplier.get();
    }

    public static void collide(final Car car) {
        System.out.println("Collided " + car.toString());
    }
    
    public void repair() {
        System.out.println("Repaired " + this.toString());
    }
}

Start using the reference method:

   @Test
    public void MethodReferenceTest() {
//        1、旧方法写法
//        final Car oldCar = Car.create(new Supplier<Car>() {
//            @Override
//            public Car get() {
//                return new Car();
//            }
//        });
//        2、jdk8的lambda
//        final Car oldCar1 = Car.create(() -> new Car());

        //3、jdk8写法
        //构造器引用  Class::new
        final Car newCar = Car.create(Car::new);

        //该方法返回的 List 与传入数组是映射关系(视图):set/get 操作直接作用于数组;直接修改数组,list 也会改变
        final List<Car> cars = Arrays.asList(newCar);
/*-----------------------------分割线---------------------------------------*/

//       1、旧方法写法
//        for (Car car : cars) {
//            Car.collide(car);
//        }
//        2、jdk8的forEach
//        cars.forEach(new Consumer<Car>() {
//            @Override
//            public void accept(Car car) {
//                Car.collide(car);
//            }
//        });
//        3、jdk8的lambda
//        cars.forEach(car -> Car.collide(car));

        //4、jdk8方法引用写法
        //类名的方法引用 Class::static_method 或者 Class::method
        cars.forEach(Car::collide);
/*-----------------------------分割线----------------------------------------*/

        final Car police = Car.create(Car::new);

//       1、jdk8的lambda
//        cars.forEach(car -> police.follow(car));

        //2、jdk8方法引用写法
        //特定对象的方法引用  instance::method
        cars.forEach(police::follow);
    }
 /*-----------------------------分割线---------------------------------------*/

        String[] stringsArray= {"4","5"};
//       1、旧方法写法
//        Arrays.sort(stringsArray, new Comparator<String>() {
//            @Override
//            public int compare(String s1, String s2) {
//                return s1.compareToIgnoreCase(s2);
//            }
//        });
//        2、jdk8的lambda
//        Arrays.sort(stringsArray,(s1,s2)->s1.compareToIgnoreCase(s2));

        //3、jdk8的方法引用
        Arrays.sort(stringsArray, String::compareToIgnoreCase);

Fourth, the default interface method

1. Definitions

The official explanation: The default method is the interface can be implementation, and do not need to go to achieve its implementation class method. We just in front of the method name to add a default keyword can be realized default method.

2, for design reasons

问:为什么要有这个特性?
答:首先,之前的接口是个双刃剑,好处是面向抽象而不是面向具体编程,缺陷是,当需要修改接口时候,需要修改全部实现该接口的类,通常能想到的解决办法是在JDK里给相关的接口添加新的方法及实现。然而,对于已经发布的版本,是没法在给接口添加新方法的同时不影响已有的实现。所以引进的默认方法。他们的目的是为了解决接口的修改与现有的实现不兼容的问题。

3、使用

(1)接口的默认方法
最基本使用,接口通过default定义默认方法,实现类无需实现该方法

interface Vehicle {
    default void print() {
        System.out.println("我是一辆车!");
    }
}

class Car implements Vehicle{

}

如果一个类实现了多个接口,且这些接口有相同的默认方法,则可以通过
重写接口的默认方法,或者使用 super 来调用指定接口的默认方法

public interface Vehicle {
   default void print(){
      System.out.println("我是一辆车!");
   }
}
public interface FourWheeler {
   default void print(){
      System.out.println("我是一辆四轮车!");
   }
}
//创建自己的默认方法,来覆盖重写接口的默认方法
public class Car implements Vehicle, FourWheeler {
   default void print(){
      System.out.println("我是一辆四轮汽车!");
   }
}
//使用 super 来调用指定接口的默认方法
public class Car implements Vehicle, FourWheeler {
   public void print(){
      Vehicle.super.print();
   }
}

(2)接口的静态默认方法
不实例化接口的时候也可以用,个人感觉失去了接口的本质,但是妥协旧代码是这样的啦

public interface Animal {
 static void putUpHands(){
     System.out.println("举手");
 }
}

class Cat {
    void catPutUpHands(){
        Animal.putUpHands();
    }
}

五、Stream

1、定义

官方解释:让你以一种声明的方式处理数据。将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。元素流在管道中经过中间操作的处理,最后由最终操作得到前面处理的结果。Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
个人解释:把数组通过.stream()或者.parallelStream()转换成流,然后通过filter、map、distinct、sorted、limit等方法进行中间处理,最后通过collect、forEach、count得出最终结果。

2、设计原因

简化数组处理

2、使用

public static void main(String[] args) {
        List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl");
        List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5, 1, 9, 10, 4, 1);
        /*=======================返回Stream<T>==========================*/
        //1、filter过滤
        strings.stream().filter(string -> !string.isEmpty());
        //2、map映射每个元素到对应的结果
        numbers.stream().map(i -> i * i);
        //3、distinct去重
        numbers.stream().distinct();
        //4、sorted排序
        numbers.stream().sorted();
        //4、limit限制数量
        numbers.stream().limit(5);
        //5、并行处理,主要适用于大数据量的数组
        strings.parallelStream();

        /*=======================对流进行转换或处理的==========================*/
        //1、collect转换成列表或字符串,Collectors 可将流转换成集合和聚合元素
        List<String> collect = strings.stream().collect(Collectors.toList());
        String collectStr = strings.stream().collect(Collectors.joining(", "));
        //2、forEach迭代流中的每个数据
        strings.stream().forEach(System.out::println);
        //3、count统计数量
        long count = strings.stream().count();

         /*=======================拓展IntStream,LongStream,DoubleStream==========================*/

         //1.1、mapToInt将Stream转换成IntStream, summaryStatistics是对IntStream数据进行汇总统计的方法,(LongStream,DoubleStream同理)
        IntSummaryStatistics summary = numbers.stream().mapToInt(x ->x).summaryStatistics();
        System.out.println(summary.getAverage());
        System.out.println(summary.getCount());
        System.out.println(summary.getMax());
        System.out.println(summary.getMin());
        System.out.println(summary.getSum());

        //1.2、IntStream,LongStream创建区间方式是一样的
        int[] range1 = IntStream.rangeClosed(13, 15).toArray();//生产区间 [a,b]      range1=[13,14,15]
        int[] range2 = IntStream.range(13, 15).toArray();//生产区间 [a,b)     range2=[13,14]
        double[] doubles = DoubleStream.of(5.33, 2.34, 5.32, 2.31, 3.51).toArray(); //doubles=[5.33, 2.34, 5.32, 2.31, 3.51]

        //1.2、IntStream的统计方法(LongStream,DoubleStream同理)
        double average = IntStream.range(13, 15).average().getAsDouble();//average=13.5
        int max = IntStream.range(13, 15).max().getAsInt(); //max=14
        int min = IntStream.range(13, 15).min().getAsInt(); //min=13
        int sum = IntStream.range(13, 15).sum(); //sum=27
    }

六、Optional 类

1、定义

官方解释:Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。

个人解释:换言之就是把变量转成Optional对象,其中null都转成Optional.empty()(就是一个空的Optional对象),然后就可以对Optional对象进行操作。好处就是发现null可选择抛出异常。

2、设计原因

不用显式进行空值检测。解决空指针异常。避免null。

3、使用

public class OptionalTest {
    public static void main(String args[]){
        handleParam(null,1);//后面两个参数自己随意写

    }
    //处理参数举例子
    static void handleParam(String a,Integer b){
        //对于处理string参数
        Optional<String> aOpt = Optional.ofNullable(a); //允许参数空。如果非空返回一个包含引用Optional实例,否则返回Optional.empty()。
        System.out.println(aOpt.isPresent());//输出aOpt是否为空
        a=aOpt.orElse("defaultValue");//如果为空,就给一个默认值defaultValue
        System.out.println(a);

        //同理对于处理int参数
        Optional<Integer> bOpt = Optional.of(b);//不允许参数空,不然会抛出异常
        b=bOpt.get();//get的时候不允许变量为空
        System.out.println(b);
    }
}

六、日期时间类

1、定义

加强对日期与时间的处理。

2、设计原因

在旧版的 Java 中,日期时间 API 存在诸多问题

  • (1)非线程安全 − java.util.Date 是非线程安全的,所有的日期类都是可变的,这是Java日期类最大的问题之一。
  • (2)设计很差 − Java的日期/时间类的定义并不一致,在java.util和java.sql的包中都有日期类,此外用于格式化和解析的类在java.text包中定义。
    java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期,将其纳入java.sql包并不合理。另外这两个类都有相同的名字,这本身就是一个非常糟糕的设计。
  • (3)时区处理麻烦 − 日期类并不提供国际化,没有时区支持,因此Java引入了java.util.Calendar和java.util.TimeZone类,但他们同样存在上述所有的问题。

3、使用

 public static void testTime() {

        // 当前详细时间
        LocalDateTime currentTime = LocalDateTime.now(); //currentTime =  2019-05-30T15:05:46.408
        // 当前年月日
        LocalDate date1 = currentTime.toLocalDate(); //date1 = 2019-05-30

        //获取详细时间的月日秒
        Month month = currentTime.getMonth();//month=MAY
        int day = currentTime.getDayOfMonth();//day=30
        int seconds = currentTime.getSecond();//seconds=46

        //替换详细时间的年月
        LocalDateTime date2 = currentTime.withDayOfMonth(10).withYear(2012);//date2 = 2012-05-10T15:05:46.408

        //自定义年月日
        LocalDate date3 = LocalDate.of(2014, Month.DECEMBER, 12);//date3= 2014-12-12

        //自定义时分
        LocalTime date4 = LocalTime.of(22, 15); //date4 = 22:15

        //解析字符串
        LocalTime date5 = LocalTime.parse("20:15:30"); //date5 = 20:15:30
        LocalDateTime date6 = LocalDateTime.parse("2019-05-30T15:05:46.408");//date6 = 2019-05-30T15:05:46.408


        // 获取当前时间日期
        ZonedDateTime date7 = ZonedDateTime.parse("2015-12-03T10:15:30+05:30[Asia/Shanghai]");//date6=2015-12-03T10:15:30+08:00[Asia/Shanghai]
        // 获取时区ID
        ZoneId id = ZoneId.of("Europe/Paris");//id= Europe/Paris
        //获取默认时区
        ZoneId defaultZone = ZoneId.systemDefault();//defaultZone=sia/Shanghai
    }

七、Base64

1、定义

官方解释:Base64工具类提供了一套静态方法获取下面三种BASE64编码器和解码器:

  • 基本:输出被映射到一组字符A-Za-z0-9+/,编码不添加任何行标,输出的解码仅支持A-Za-z0-9+/。
  • URL:输出映射到一组字符A-Za-z0-9+_,输出是URL和文件。
  • MIME:输出隐射到MIME友好格式。输出每行不超过76字符,并且使用'\r'并跟随'\n'作为分割。编码输出最后没有行分割。

2、使用

public static void main(String args[]) {
       try {

           // 使用基本编码
           String base64encodedString = Base64.getEncoder().encodeToString("我是测试字符串".getBytes("utf-8"));//base64encodedString = "5oiR5piv5rWL6K+V5a2X56ym5Liy"

           // 解码
           byte[] base64decodedBytes = Base64.getDecoder().decode(base64encodedString);
           String base64decodedStr= new String(base64decodedBytes, "utf-8");//base64decodedStr = "我是测试字符串"

           //使用URL编码
           String urlEncodedString = Base64.getUrlEncoder().encodeToString("testUrl?java8".getBytes("utf-8"));//urlEncodedString = "VHV0b3JpYWxzUG9pbnQ_amF2YTg="


           //使用MIME编码
           String mimeEncodedString = Base64.getMimeEncoder().encodeToString(("QWERTYUIOP-ASDFGHJKL-ZXCVBNM").getBytes("utf-8"));//mimeEncodedString = "UVdFUlRZVUlPUC1BU0RGR0hKS0wtWlhDVkJOTQ=="

       }catch(UnsupportedEncodingException e){
           System.out.println("Error :" + e.getMessage());
       }
   }

Guess you like

Origin www.cnblogs.com/ranandrun/p/java8.html