jdk1.8新增特性

接口的默认方法 default关键字

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

lambda表达式

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

函数式编程

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

1.8之前:

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

lambda:

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

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

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

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

ArrayList<Student> 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> {
    P creat(String nikename,String username);
}

访问构造函数

 PersonFactory<Person> 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>{
        T doThing();
    }
    

    测试

    Action<String> 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,P> {
        T requiredAction(P something);
    }
    

    测试

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

新增函数式接口

Predicate接口

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

demo

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

Function接口

   @FunctionalInterface
   public interface Function<T, R> {
       R apply(T t);
       default <V> Function<V, R> compose(Function<? super V, ? extends T> before);
       default <V> Function<T, V> andThen(Function<? super R, ? extends V> after);
       static <T> Function<T, T> identity();
   }

demo

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

Supplier接口

Supplier

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

demo

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

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

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

Consumer接口

Consumer

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

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

demo:

   public class ConsumerDemo {
       public static void main(String[] args) {
           Consumer<String> first = (o)-> System.out.println(o+"1");
           Consumer<String> 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<User> getInstace(User str){
        // 这种实例化方式参数可以为null
        Optional<User> strOption = Optional.ofNullable(str);
        // 这种实例化方式参数不能为null,否则会报空指针异常
        Optional<User> str1 = Optional.of(str);
        return strOption;
    }

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

    public static Optional<User> filter(User user){
        // 过滤容器内元素,使用predicate接口,如果test方法为false则返回一个空的容器
        Optional<User> 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升级的读写锁

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,284评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,115评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,614评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,671评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,699评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,562评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,309评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,223评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,668评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,859评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,981评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,705评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,310评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,904评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,023评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,146评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,933评论 2 355