jdk1.8新增特性

接口的默认方法 default关键字

可以在接口中定义方法的默认实现,并且实现类也可以选择是否重新默认实现。

lambda表达式

新增了@FunctionalInterface注解,该注解添加在只有一个抽象方法的接口上,表示可以作为函数传入。如果被添加该注解的接口有多个抽象方法,则会编译不通过。

函数式编程

以前在使用像Comparator这种接口时,一般是使用匿名内部类来实现,还有就是实现Runable接口等。

1.8之前:

 ArrayList students = new ArrayList<>(10);
        students.sort(new Comparator() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });

lambda:

        ArrayList students = new ArrayList<>(10);
        students.sort((Student o1,Student o2) -> o1.getName().compareTo(o2.getName()));

lambda简化:省去参数类型等定义

 ArrayList students = new ArrayList<>(10);
        students.sort((o1,o2) -> o1.getName().compareTo(o2.getName()));

使用Comparator的静态方法,传入比较的key的方法函数

ArrayList students = new ArrayList<>(10);
        students.sort(Comparator.comparing(Student::getName));

引入lambda表达式后,可以使这种实现更为简单。

lambda表达式内可以对静态变量和对象变量进行读写,对局部变量只能够读,并且被表达式内读的局部变量在之后不能被改变(类似于final)。

双冒号::的使用

可以使用双冒号来访问类的构造函数,静态函数和对象函数.

  1. 构造函数:

定义Person类

public class Person {
Person(String nikename,String username){
        this.nikename=nikename;
        this.username=username;
    }
    private String nikename;
    private String username;
}

定义PersonFactory接口

@FunctionalInterface
public interface PersonFactory

{ P creat(String nikename,String username); }

访问构造函数

 PersonFactory personFactory = Person::new;
 Person person = personFactory.creat("羊肉小笼包", "大哥你好");

在上面的代码中,Person::new相当于create(String,String)方法的实现,而这个实现就是Person类的构造函数,相当于使用构造函数实现接口的唯一抽象方法。

  1. 静态方法

    Person类中有一个静态方法run

    public class Person {
     public static String run(){
            return "Im running!";
        }
    }
    

    定义Action接口,内有一个抽象方法doThing

    @FunctionalInterface
    public interface Action{
        T doThing();
    }
    

    测试

    Action run = Person::run;
            System.out.println(run.doThing());
    // 打印出"Im running!"
    
  2. 实例方法

    Person类中有一个实例方法eat

    public class Person {
    public String eat(String food){
            return food + " is delicious!";
        }
        }
    

    定义接口LifeAction

    @FunctionalInterface
    public interface LifeAction {
        T requiredAction(P something);
    }
    

    测试

    Person person = new Person();
    LifeAction eat = person::eat;
    System.out.println(eat.requiredAction("noodle"));
    // 打印noodle is delicious!
    

新增函数式接口

Predicate接口

   @FunctionalInterface
   public interface Predicate {
       boolean test(T t);
       default Predicate and(Predicate other);
    default Predicate negate();
       default Predicate or(Predicate other);
       static  Predicate isEqual(Object targetRef);
   }

demo

     private static boolean check(Integer num){
           // 使用静态方法根据一个参数初始化
           Predicate equal = Predicate.isEqual(num);
           // 使用一个lambda表达式初始化
           Predicate checkNum = (i)->i>1;
           // 将两种判断取逻辑或(有短路)default方法
           Predicate or = checkNum.or((i -> i < -1));
           // 将两种判断取逻辑与(有短路)default方法
           Predicate and = or.and((i) -> i == 1);
           // 将判断取反
           Predicate negate = and.negate();
           return or.test(num);
       }
 
 

Function接口

   @FunctionalInterface
   public interface Function {
       R apply(T t);
       default  Function compose(Function before);
       default  Function andThen(Function after);
       static  Function identity();
   }

demo

           // 返回参数本身的function
           Function identity = Function.identity();
           // 定义一个有逻辑的function
           Function a = (s)->s+" 11111111";
           // 定义一个有后续逻辑的function,先执行的function的返回值
        // 就是后执行的function的参数,类型需要匹配
           Function function = a.andThen((s) -> s+" 33333333");
           // 定义一个有前置逻辑的function,前置执行的function的
        // 返回值就是该function的参数
           Function compose = a.compose((s) -> s + " 222222");
   

Supplier接口

Supplier

   @FunctionalInterface
   public interface Supplier {
       T get();
   }

demo

   public class SupplierDemo {
       public static void main(String[] args) {
           Supplier supplier = SupplierDemo::new;
           SupplierDemo supplierDemo = supplier.get();
           Supplier a = SupplierDemo::a;
           System.out.println(a.get());
           //打印aaaa
       }
       public static String a(){
           return "aaaa";
       }
   }

Suplier接口可以以任何无参数的类中方法作为实现,

当然无参数类中方法必须无重写方法。

Consumer接口

Consumer

这个接口就是封装了一个消费的操作,然后有一个对传入数据的二次消费的默认实现

   @FunctionalInterface
   public interface Consumer {
       void accept(T t);
       default Consumer andThen(Consumer after) {
           Objects.requireNonNull(after);
           return (T t) -> { accept(t); after.accept(t); };
       }
   }

demo:

   public class ConsumerDemo {
       public static void main(String[] args) {
           Consumer first = (o)-> System.out.println(o+"1");
           Consumer second = first.andThen((o) -> System.out.println(o + ".....2"));
           second.accept("parameter");
       }
   }
   //打印
   //parameter1
   //parameter.....2

Comparator接口

该接口是1.2版本中添加的接口,这次1.8版本将这个接口添加了@FunctionInterface注解,并且添加了多个静态方法和默认实现。

具体请看另一篇文章:

Comparetor接口和Comparable接口的区别

集合的Stream操作

串行stream:Collection.stream

并行stream:Collection.parallelStream

使用集合的Stream操作是不影响原Collection的值的。

过滤元素

其中Filter方法的参数是Predicate接口,也就是判断逻辑

list.stream().filter(s -> s.startsWith("b")).forEach(System.out::println);

集合排序

sorted方法无参时是使用自然排序,如果有参,参数为Comparator接口

list.parallelStream().sorted().forEach(System.out::println);
list.parallelStream().sorted(String::compareTo).forEach(System.out::println);

集合迭代

forEach方法参数为Consumer接口

list.forEach(System.out::println);
list.stream().forEach(System.out::println);
list.parallelStream().forEach(System.out::println);

集合元素处理

map方法参数为Function接口,需要实现对集合元素处理逻辑,返回新的Stream

list.stream().map((String o)->Integer.valueOf(o.substring(3))).forEach(System.out::println);

结合元素匹配

类似于contain方法,Stream的match方法可以根据实现的匹配逻辑判断集合中是否含有该种元素。方法参数是Predicate接口,返回值是boolean。

全部匹配
list.stream().allMatch(o -> o.startsWith("a"))
是否存在匹配
list.stream().anyMatch(o->o.startsWith("a"));
无匹配
list.stream().noneMatch(o->o.startsWith("a"));

集合元素计数

list.stream.filter(s->s.startsWith("a").count())

集合计算

System.out.println(list.stream().reduce("head:", (o1, o2) -> o1 + o2));
// 打印出head:元素拼接
// 其中第一个参数是作为初始变量,作为o1传入了方法内

Optional类

一个封装泛型数据的容器,可以很方便的用来判断数据是否为null,可以作为方法的返回类型和方法入参。

demo

 public static Optional getInstace(User str){
        // 这种实例化方式参数可以为null
        Optional strOption = Optional.ofNullable(str);
        // 这种实例化方式参数不能为null,否则会报空指针异常
        Optional str1 = Optional.of(str);
        return strOption;
    }

    public static User orElse(User user){
        // 可以在获得元素的时候有一个默认
        Optional user1 = Optional.ofNullable(user);
        User et = user1.orElse(new User("3", "ET"));
        return et;
    }
    public static User orElseGet(User user){
        // 在获取元素时如果为null,调用一个Supplier的实现构造一个新的元素
        Optional user1 = Optional.ofNullable(user);
        return user1.orElseGet(() -> new User("3", "ET"));
    }

    public static Optional filter(User user){
        // 过滤容器内元素,使用predicate接口,如果test方法为false则返回一个空的容器
        Optional user1 = Optional.ofNullable(user);
        return user1.filter((o) -> o.getSex() == null);
    }

新的时间日期API:

LocalDate

获取当前的date
        // 获取指定zone现在的date
        String s = LocalDate.now(ZoneId.of("America/Chicago")).toString();
        // 获取当前地区现在的date
        String s1 = LocalDate.now().toString();
        // 获取当前zone现在的date
        LocalDate.now(Clock.systemDefaultZone()).toString();

根据指定年月日获取localDate
        // 根据指定的年月日生成localDate
        LocalDate of = LocalDate.of(year, month, day);
        // 这里是把月份int用枚举值代替
        LocalDate of1 = LocalDate.of(year, Month.APRIL, day);
        // 1970-01-01加上Long类型参数天的日期
        String s = LocalDate.ofEpochDay(356 * 10L).toString();

获取当月的特殊日期

        // 获取本月的第一天日期
        LocalDate firstDay = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());
        // 获取本月的最后一天
        LocalDate lastDay = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth());
        // 今天是本月几日
        int dayOfMonth = LocalDate.now().getDayOfMonth();
        // 今天是周几
        int value = LocalDate.now().getDayOfWeek().getValue();
        // 获取当前年份
        int year1 = LocalDate.now().getYear();
        // 获取当前月份
        int month1 = LocalDate.now().getMonth().getValue();

LocalTime

与LocalDate类似

获取LocalTime实例
        // 该实例会生成带有毫秒数的一个LocalTime
        LocalTime now = LocalTime.now();
        // 其参数为,时、分、秒、纳秒
        LocalTime of = LocalTime.of(1, 2, 2, 3);
        LocalTime of1 = LocalTime.of(1, 2, 3);
操作LocalTime实例
        LocalTime now = LocalTime.now();
        LocalTime localTime = now.plusHours(1);
        LocalTime localTime1 = now.withMinute(12);
        LocalTime localTime2 = localTime1.withHour(1);

LocalDateTime

该类包含了LocalDate和LocalTime的一些方法,如getMonth,getHour等。

LocalDate、LocalTime和LocalDateTime之间的转化

        LocalDateTime of1 = LocalDateTime.of(LocalDate.now(), LocalTime.now());
        LocalDate localDate = of1.toLocalDate();
        LocalTime localTime = of1.toLocalTime();

DateTimeFormatter

格式化LocalDate、LocalTime和LocalDateTime三个类,使用方式相同

转为格式String
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime now = LocalDateTime.now();
        String format = now.format(dateTimeFormatter);

String转日期时间类
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String dateTimeStr = "1992-11-02 11:32:23";
        TemporalAccessor parse = dateTimeFormatter.parse(dateTimeStr);
        LocalDateTime from = LocalDateTime.from(parse);

Clock

Clock是一个抽象类,在其内部有四个内部类:

  1. SystemClock
  2. FixedClock
  3. OffsetClock
  4. TickClock

支持多重注解

原来需要使用数据类型存储多个相同的注解,现在可以将多个形同注解加载同一处,给注解添加@Repatable元注解即可,

编译器会自动帮你将相同注解存储在注解的数组属性里面。

StampedLock升级的读写锁

你可能感兴趣的:(jdk1.8新增特性)