java8新特性

java8新特性

Lambda(核心)

用于快速的实现匿名内部类中的方法。

例子:
Runnable r = new Runnable() {
    @Override
    public void run() {
        System.out.println("do something.");      
    }
}

如果我们想要写一些线程,而每个线程中的实现很简单,就像例子中的只在控制台打印一句话,那么还需要多写4行代码,很麻烦,可读性也不高。下面,看下lambda的实现:

Runnable r = () -> System.out.println("do something.");
lambda的基础语法:
expression = (variable) -> action
  • variable:可以是一个变量,一个占位符,也可以是多个变量(x,y,z)。

  • action:实现的代码逻辑,如果一行处理不完,可以用“{}”将执行的代码包起来。

  • expression:返回的值。

使用姿势:
public class FunctionInterfaceDemo {
    @FunctionalInterface
    interface Predicate<T> {
        boolean test(T t);
    }
    /**
     * 执行Predicate判断
     *
     * @param age       年龄
     * @param predicate Predicate函数式接口
     * @return          返回布尔类型结果
     */
    public static boolean doPredicate(int age, Predicate<Integer> predicate) {
        return predicate.test(age);
    }
     
    public static void main(String[] args) {
        boolean isAdult = doPredicate(20, x -> x >= 18);
        System.out.println(isAdult);
    }
}

如上述代码所示,当一个接口类中只有一个方法,且接口类作为变量传入函数中的时候,就可以使用lambda函数。

四大内置接口

java8为lambda提供了4大内置接口,分别消费型接口、供给型接口、函数型接口、断言型接口。其它的很多接口都是这四种接口衍生出来的,我们可以根据入参和出参类型的不同灵活使用。

消费型接口示例(只有入参):

//消费money
public static void donation(Integer money, Consumer<Integer> consumer){
    consumer.accept(money);  
}
public static void main(String[] args) {
    donation(1000, money -> System.out.println("好心的麦乐迪为Blade捐赠了"+money+"元")) ;
}

供给型接口示例(只有出参):

//传入随机数,返回集合
public static List<Integer> supply(Integer num, Supplier<Integer> supplier){
       List<Integer> resultList = new ArrayList<Integer>()   ;
       for(int x=0;x<num;x++)  
           resultList.add(supplier.get());
       return resultList ;
}
public static void main(String[] args) {
    List<Integer> list = supply(10,() -> (int)(Math.random()*100));
    list.forEach(System.out::println);
}

函数型接口示例(入参出参都有):

//转换字符串为Integer
public static Integer convert(String str, Function<String, Integer> function) {
    return function.apply(str);
}
public static void main(String[] args) {
    Integer value = convert("28", x -> Integer.parseInt(x));
}    

断言型接口示例(有入参,出参为boolean类型):

//筛选出只有两个字的水果
public static List<String> filter(List<String> fruit, Predicate<String> predicate){
    List<String> f = new ArrayList<>();
    for (String s : fruit) {
        if(predicate.test(s)){
            f.add(s);
        }
    }
    return f;
}
public static void main(String[] args) {
    List<String> fruit = Arrays.asList("香蕉", "哈密瓜", "榴莲", "火龙果", "水蜜桃");
    List<String> newFruit = filter(fruit, (f) -> f.length() == 2);
    System.out.println(newFruit);
}

stream流

用于快速处理集合的数据(一般用于查找过滤)

创建流

我们常用的创建流的方式有两种,一是集合创建流(最常用),二是数组创建流,也有其它方式创建流,但是一般不用。

//1. 通过集合创建stream(推荐)
List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();

//2. 通过Arrays中的静态方法
Integer[] intArray = new Integer[10];
Stream<Integer> stream2 = Arrays.stream(intArray);
处理过程
  1. 获取流。
  2. 中间操作。
  3. 终止操作。

常见的流处理函数

/**
 * Stream的中间操作:
     * filter:排除元素
     * distinct:去重
     * limit:给定数量
     * skip:跳过几个数量
     * map:实现函数
     * flatMap:扁平化
     * sorted:排序
 * Stream的终止操作:
     * allMatch,anyMatch,noneMatch:是否匹配元素
     * findFirst,findAny:返回元素
     * count,max,min:计数,最大,最小
     * forEach:迭代
     * reduce:归约
 */
并行流

java7中的Fork/Join框架,会将一个大任务拆分成多个小任务,并行的去执行,然后将各个小任务执行的结果进行合并,最终返回结果。缺点是代码太难写,每实现一次要写好多定制化的代码。

java8中提供了并行流的方式,底层用的就是Fork/Join框架,但只需要一句代码:

list.parallelStream()

与java7相比,人性化了很多。

总结
  1. stream流函数中需要传入的参数都是java8内置的lambda接口,因此,推荐在函数中直接写lambda。
  2. stream形式适用于集合数据快速的查找过滤等操作,当需要对集合中的数据进行很多的业务逻辑处理的时候,建议使用增强for循环。主要原因是lamdba写法不适合写的过长,处理过多业务逻辑,不利于后期维护。
练习
List<Transaction> transactions = null;

@Before
public void before(){
    //交易员
    Trader raoul = new Trader("Raoul", "Cambridge");
    Trader mario = new Trader("Mario", "Milan");
    Trader alan = new Trader("Alan", "Cambridge");
    Trader brian = new Trader("Brian", "Cambridge");

    //交易
    transactions = Arrays.asList(
            new Transaction(brian, 2011, 300),
            new Transaction(raoul, 2011, 1000),
            new Transaction(raoul, 2011, 400),
            new Transaction(mario, 2012, 710),
            new Transaction(mario, 2012, 700),
            new Transaction(alan, 2012, 950)
    );
}

/**
 * 1. 找出2011年发生的所有交易, 并按交易额排序(从低到高)
 */
@Test
public void test1() {
    transactions.stream()
            .filter((t) -> t.getYear() == 2011)
            .sorted(Comparator.comparingInt(Transaction::getValue))
            .forEach(System.out::println);
}

/**
 * 2. 交易员都在哪些不同的城市工作过?
 */
@Test
public void test2() {
    transactions.stream()
            .map((e) -> e.getTrader().getCity())
            .distinct()
            .forEach(System.out::println);
}

/**
 * 3. 查找所有来自剑桥的交易员,并按姓名排序
 */
@Test
public void test3() {
    transactions.stream()
            .filter((e) -> e.getTrader().getCity().equals("Cambridge"))
            .map((e) -> e.getTrader().getName())
            .sorted(Comparator.naturalOrder())
            .distinct()
            .forEach(System.out::println);
}

/**
 * 4. 返回所有交易员的姓名字符串,按字母顺序排序
 */
@Test
public void test4() {
    transactions.stream()
            .map((e) -> e.getTrader().getName())
            .sorted(Comparator.naturalOrder())
            .forEach(System.out::println);
}

/**
 * 5. 有没有交易员是在米兰工作的
 */
@Test
public void test5() {
    boolean b = transactions.stream()
            .anyMatch((e) -> e.getTrader().getCity().equals("Milan"));
    System.out.println(b);
}

/**
 * 6. 打印生活在剑桥的交易员的所有交易额之和
 */
@Test
public void test6() {
    Optional<Integer> optional = transactions.stream()
            .filter((e) -> e.getTrader().getCity().equals("Cambridge"))
            .map(Transaction::getValue)
            .reduce(Integer::sum);
    System.out.println(optional.get());
}

/**
 * 7. 所有交易中,最高的交易额是多少
 */
@Test
public void test7() {
    Optional<Integer> optional = transactions.stream()
            .map(Transaction::getValue)
            .max(Integer::compareTo);
    System.out.println(optional.get());
}

/**
 * 8. 找到交易额最小的交易
 */
@Test
public void test8() {
    Optional<Transaction> optional = transactions.stream()
            .min(Comparator.comparingInt(Transaction::getValue));
    System.out.println(optional.get());
}

时间API

简介
  1. java8对时间的api做了整理,主要为下面这三个类:LocalDate, LocalTime, LocalDateTime。从类名就可以看出,一个是日期,一个是时间,一个是全有。
  2. 我们平时使用的时候,尽量使用LocalDateTime。
  3. 在java8之前,我们使用的时间戳日期转换工具SimpleDateFormat是线程不安全的,在使用的时候没法抽成一个静态工具类,需要在每一个线程下重新new一个SimpleDateFormat。java8中提供的DateTimeFormatter则是线程安全的。
开发中常用例子

1--获取当前时间戳

@Test
public void test1() {
    //包含了日期和时间,可以转成秒,毫秒
    Instant timestamp = Instant.now();
    System.out.println(timestamp);
    //毫秒
    long milli = timestamp.toEpochMilli();
    System.out.println(milli);
    long second = timestamp.getEpochSecond();
    System.out.println(second);

}

2--时间戳与需要的日期格式相互转换

/**
 * 2.1 时间戳转成想要的日期格式
 */
@Test
public void test2() {
    String pattern = "yyyy-MM-dd HH:mm:ss";
    long time = Instant.now().toEpochMilli();
    //时间戳转成日期
    //1. 时间戳转成标准日期
    LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneId.systemDefault());
    System.out.println(localDateTime);
    //2. 标准日期转成我们需要的格式
    DateTimeFormatter df = DateTimeFormatter.ofPattern(pattern);
    String format = df.format(localDateTime);
    System.out.println(format);
}

/**
 * 2.2 给定任意日期格式转成时间戳
 */
@Test
public void test3() {
    String pattern = "yyyy-MM-dd HH:mm:ss";
    //1. 将日期格式转成标准日期
    DateTimeFormatter df = DateTimeFormatter.ofPattern(pattern);
    LocalDateTime localDateTime = LocalDateTime.parse("2018-12-17 10:00:00", df);
    System.out.println(localDateTime);
    //2. 转换成时间戳
    long milli = localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    System.out.println(milli);

}

3--时间日期差计算

/**
 * 3.1 计算时间差
 */
@Test
public void test4() throws InterruptedException {
    Instant ins1 = Instant.now();
    System.out.println(ins1.toEpochMilli());
    Thread.sleep(1000);
    Instant ins2 = Instant.now();
    System.out.println(ins2.toEpochMilli());
    long milli = Duration.between(ins1, ins2).toMillis();
    System.out.println(milli);
}


/**
 * 3.2 计算日期差
 */
@Test
public void test5() {
    LocalDate now = LocalDate.now();
    System.out.println(now);
    LocalDate birth = LocalDate.of(1994, 11,26);
    System.out.println(birth);
    //相隔日期
    Period period = Period.between(birth, now);
    System.out.println(period.getYears() + "-" + period.getMonths() + "-" + period.getDays());
    //相隔多少天
    long dayDiff = ChronoUnit.DAYS.between(birth, now);
    System.out.println(dayDiff);
}

4--日期加减

@Test
public void test6() {
    LocalDateTime today = LocalDateTime.now();
    LocalDateTime tor = today.plusDays(1);
    LocalDateTime yes = today.minusDays(1);
    System.out.println(yes);
    System.out.println(today);
    System.out.println(tor);
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 230,362评论 6 544
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 99,577评论 3 429
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 178,486评论 0 383
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 63,852评论 1 317
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 72,600评论 6 412
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 55,944评论 1 328
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 43,944评论 3 447
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 43,108评论 0 290
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 49,652评论 1 336
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 41,385评论 3 358
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 43,616评论 1 374
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 39,111评论 5 364
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,798评论 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 35,205评论 0 28
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 36,537评论 1 295
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 52,334评论 3 400
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 48,570评论 2 379

推荐阅读更多精彩内容

  • java8新特性 原创者:文思 一、特性简介 速度更快 代码更少,增加了Lambda 强大的Stream API ...
    文思li阅读 3,064评论 1 1
  • 一、重要数据结构和JVM的改动 1.HashMap的改动 HashMap维护了一个Entry数组,put(K ke...
    一只爱java的猫阅读 488评论 0 0
  • 前言: 北京时间2018年9月26日,Oracle官方发布Java 11。既然版本都更新到11了,现在才来学8是不...
    贪挽懒月阅读 1,004评论 0 16
  • 对于Java开发者来说,Java8的版本显然是一个具有里程碑意义的版本,蕴含了许多令人激动的新特性,如果能利用好这...
    jackcooper阅读 1,035评论 0 6
  • 对于Java开发者来说,Java8的版本显然是一个具有里程碑意义的版本,蕴含了许多令人激动的新特性,如果能利用好这...
    huanfuan阅读 571评论 0 9