Java8新特性详解

1.Java8新特性编程风格

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Java8Tester {
    public static void main(String[] args) {
        List<Integer> list1 = new ArrayList<>();
        list1.add(14);
        list1.add(233);
        list1.add(3232);
        list1.add(23);
        list1.add(90);

        List<String> list2 = new ArrayList<>();
        list2.add("google");
        list2.add("baidu");
        list2.add("taobao");
        list2.add("jingdong");
        list2.add("tiaomao");

        java7TesterSort(list1);
        System.out.println("java7 :"+list1);


        java8TesterSort(list2);
        System.out.println("java8 :"+list2);

    }

    private static void java7TesterSort(List<Integer> list1) {
        Collections.sort(list1, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1.compareTo(o2);
            }
        });
    }


    private static void java8TesterSort(List<String> list1) {
        Collections.sort(list1, (o1, o2) -> o1.compareTo(o2));
    }

}

输出结果为:

ps:

1)运行main方法时,报了启动错误,

objc[63766]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/bin/java (0x10390d4c0) and /Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x1039e94e0). One of the two will be used. Which one is undefined.

解决方法:Help-->Edit Custom Properties-->Create 然后在idea.properties里增加

idea.no.launcher=true

问题解决

2)idea输出日志的快捷键与eclipse不同,IDEA使用sout ,Eclipse使用syso

 

2.Lambda表达式实例

public class Java8Tester {
    public static void main(String[] args) {

        MathOperaion add = (a, b) -> (a + b);

        System.out.println(operate(1, 2, add));

        SayHello sayHello=message -> System.out.println("Hello "+message);

        sayHello.sayHello("hzb");
    }


    interface MathOperaion {
        int operation(int a, int b);
    }

    interface SayHello{
        void sayHello(String message);
    }

    private static int operate(int a, int b, MathOperaion mathOperaion) {
        return mathOperaion.operation(a, b);
    }
}

输出结果为:

 

public class Java8Tester {
    public static void main(String[] args) {

        int num = 1;

        Convert<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num));

        s.convert(2);

        //num = 5;
    }


    interface Convert<T1, T2> {
        void convert(int i);
    }


}

返回结果为3,如放开注释num=5,更改局部变量,则出现异常,如下图所示:

说明:

          lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义)

          在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量。

3. 双冒号 ::  的用法

import java.util.ArrayList;
import java.util.List;

public class Java8Tester {
    public static void main(String[] args) {

        List<String> list = new ArrayList<>();
        list.add("China");
        list.add("America");
        list.add("France");
        list.add("Germany");
        list.add("Italy");

        list.forEach(Java8Tester::printStr);
    }

    public static void printStr(String str) {
        System.out.println("输出结果为:" + str);
    }

}

双冒号就是把方法当作参数传入stream内部,让stream的每一个元素都进入该方法执行,输出结果如下图所示:

Java8中,Iterable 实现了forEach方法,调用了Consumer 接口的accept方法,执行传入的方法参数,源码如下:

   /**
     * Performs the given action for each element of the {@code Iterable}
     * until all elements have been processed or the action throws an
     * exception.  Unless otherwise specified by the implementing class,
     * actions are performed in the order of iteration (if an iteration order
     * is specified).  Exceptions thrown by the action are relayed to the
     * caller.
     *
     * @implSpec
     * <p>The default implementation behaves as if:
     * <pre>{@code
     *     for (T t : this)
     *         action.accept(t);
     * }</pre>
     *
     * @param action The action to be performed for each element
     * @throws NullPointerException if the specified action is null
     * @since 1.8
     */
    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }

4.函数式接口Predicate<T>的用法

它接受一个输入参数T,返回一个boolean值,示例代码如下:

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

public class Java8Tester {
    public static void main(String[] args) {

        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        System.out.println("输出所有参数:");

        eval(list, n -> true);

        System.out.println();
        System.out.println("输出所有偶数:");

        eval(list, n -> (n % 2 == 0));

        System.out.println();
        System.out.println("输出所有大于3的数:");

        eval(list, n -> n > 3);

    }

    private static void eval(List<Integer> list, Predicate<Integer> predicate) {

        //第一种方法
        for (Integer n : list) {
            if (predicate.test(n)) {
                System.out.print(n + " ");
            }
        }
        //第二种方法
        list.stream().filter(predicate).forEach(System.out::print);
    }

}

输出结果如下图所示:

ps:@FunctionalInterface主要用于编译级代码检查,对是不是函数式接口无影响,个人感觉等同于@Override

5.默认方法

参考链接:https://blog.csdn.net/tony308001970/article/details/81937765

6.Stream

stream():为集合创建串行流

parallel():为集合创建并行流

filter():筛选符合条件的元素

forEach():迭代流中的每个数据

map():映射到每个元素对应的结果(可以对元素进行处理并返回 如:map(x -> x*x).distinct())

sorted():排序

Collectors():使用了很多归约操作,将流转成集合和聚合元素

IntSummaryStatistics:收集器(max,min,average,sum)如mapToInt((x) -> x).summaryStatistics()

import java.util.Arrays;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

public class Java8Tester {
    public static void main(String[] args) {

        System.out.println("使用 Java 8: ");


        List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl");
        System.out.println("列表: " + strings);
        // 计算空字符串
        long count = strings.stream().filter(s -> s.isEmpty()).count();
        System.out.println("空字符数量为: " + count);
        count = strings.stream().filter(s -> s.length() == 3).count();
        System.out.println("字符串长度为 3 的数量为: " + count);
        // 删除空字符串
        List<String> filtered = strings.stream().filter(s -> !s.isEmpty()).collect(Collectors.toList());
        System.out.println("筛选后的列表: " + filtered);
        // 删除空字符串,并使用逗号把它们合并起来
        String mergedString = strings.stream().filter(s -> !s.isEmpty()).collect(Collectors.joining(","));
        System.out.println("合并字符串: " + mergedString);


        List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
        // 获取列表元素平方数
        List<Integer> squaresList = numbers.stream().map(i -> i * i).distinct().collect(Collectors.toList());
        System.out.println("平方数列表: " + squaresList);


        List<Integer> integers = Arrays.asList(1, 2, 13, 4, 15, 6, 17, 8, 19);
        IntSummaryStatistics intSummaryStatistics = integers.stream().mapToInt(i -> i).summaryStatistics();
        System.out.println("列表: " + integers);
        System.out.println("列表中最大的数 : " + intSummaryStatistics.getMax());
        System.out.println("列表中最小的数 : " + intSummaryStatistics.getMin());
        System.out.println("所有数之和 : " + intSummaryStatistics.getSum());
        System.out.println("平均数 : " + intSummaryStatistics.getAverage());


        System.out.println("随机数: ");
        Random random = new Random();
        // 输出10个排序的随机数 
        random.ints().limit(10).sorted().forEach(System.out::println);

    }


}

输出结果如下图所示:

7.Optional类

      Optional类是个容器,可以保存类型T的值,可以很好的解决空指针异常

Optional.ofNullable(value):允许传递参数值为null

Optional.of(value):如果值为null,则抛出空指针异常NullPointerException

value.isPresent():判断值是否存在,如果存在返回true,否则返回false

value.orElse(value):如果值存在,返回此值,否则返回默认值

value.get():如果值存在,取得此值

 

import java.util.Optional;

public class Java8Tester {
    public static void main(String[] args) {

        Java8Tester java8Tester = new Java8Tester();

        Integer value1 = null;
        Integer value2 = new Integer(10);

        //允许传递参数为null
        Optional<Integer> optional1 = Optional.ofNullable(value1);
        //如果值为null,则跑出空指针异常NullPointerException
        Optional<Integer> optional2 = Optional.of(value2);

        System.out.println(java8Tester.sum(optional1, optional2));


    }

    public Integer sum(Optional<Integer> value1, Optional<Integer> value2) {
        System.out.println("第一个参数存在: " + value1.isPresent());
        System.out.println("第二个参数存在: " + value2.isPresent());

        //如果值存在则返回此值,否则返回默认值
        Integer returnValue1 = value1.orElse(new Integer(0));

        //取得存在的值
        Integer returnValue2 = value2.get();

        return returnValue1 + returnValue2;
    }


}

输出结果如下图所示:

8.LocaLDateTime的使用

        如果是JDK8的应用,可以使用Instant代替Date,LocalDateTime代替Calendar,DateTimeFormatter代替SimpleDateFormat,官方给出的解释: simple beautiful strong immutable thread-safe(简单优秀健壮不可变 线程安全)

      使用Spring Boot时,使用LocalDatetime类时,接收前端传递的数据时,需要在参数之前加上@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")或者@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")注解,否则接收不到数据,而且会报错

如下是LocalDateTime和其他类型的转换工具类:

import org.apache.commons.lang.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;


public class Java8Tester {

    public static void main(String[] args) {

        String dateStr = "2019-08-09 09:23:22";

        LocalDateTime localDateTime = LocalDateTime.now();

        Date date = new Date();

        System.out.println("LocalDateTime类型:" + localDateTime);

        System.out.println("LocalDateTime类型转成String类型:" + Java8Tester.localDateToStr(localDateTime, "yyyy-MM-dd"));

        System.out.println("LocalDateTime类型转成Date类型:" + Java8Tester.localDateToDate(localDateTime));

        System.out.println("Date类型转成LocalDateTime类型: " + Java8Tester.dateToLocalDateTime(date));

        System.out.println("String类型转成LocalDateTime类型: " + Java8Tester.strToLocalDateTime(dateStr));

        System.out.println("String类型转成Date类型: " + Java8Tester.strToDate(dateStr, "yyyy-MM-dd HH:mm:ss"));

    }

    /**
     * LocalDateTime类型转成String类型
     *
     * @param localDateTime
     * @param pattern
     * @return
     */
    public static String localDateToStr(LocalDateTime localDateTime, String pattern) {

        try {
            if (localDateTime != null && StringUtils.isNotBlank(pattern)) {
                DateTimeFormatter df = DateTimeFormatter.ofPattern(pattern);
                return df.format(localDateTime);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return "";
    }

    /**
     * LocalDateTime类型转成Date类型
     *
     * @param localDateTime
     * @return
     */
    public static Date localDateToDate(LocalDateTime localDateTime) {
        //获取系统默认时区
        ZoneId zoneId = ZoneId.systemDefault();

        //将将此日期时间与时区组合以创建ZonedDateTime,并转成Instant类型
        Instant instant = localDateTime.atZone(zoneId).toInstant();

        //再将Instant类型转成Date类型
        return Date.from(instant);
    }

    /**
     * Date类型装成LocalDateTime类型
     *
     * @param date
     * @return
     */
    public static LocalDateTime dateToLocalDateTime(Date date) {

        Instant instant = date.toInstant();

        ZoneId zoneId = ZoneId.systemDefault();

        return LocalDateTime.ofInstant(instant, zoneId);
    }

    /**
     * String类型转成LocalDateTime类型
     *
     * @param dateStr
     * @return
     */
    public static LocalDateTime strToLocalDateTime(String dateStr) {
        if (StringUtils.isEmpty(dateStr)) {
            return null;
        }

        dateStr = dateStr.replace("T", " ").trim();

        if (dateStr.contains("T") && dateStr.length() > 11) {
            dateStr.replace("T", " ");
            if (dateStr.length() == 16) {
                dateStr = dateStr + ":00";
            }
        } else if (dateStr.contains("T") && dateStr.length() == 11) {
            dateStr.replace("T", " 00:00:00");
        } else if (dateStr.length() == 10) {
            dateStr = dateStr + " 00:00:00";
        }

        Date date = Java8Tester.strToDate(dateStr, "yyyy-MM-dd HH:mm:ss");

        if (null == date) {
            return null;
        }

        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    }

    /**
     * String类型转成Date类型
     *
     * @param dateStr
     * @param pattern
     * @return
     */
    public static Date strToDate(String dateStr, String pattern) {
        if (StringUtils.isEmpty(dateStr)) {
            return null;
        }

        SimpleDateFormat sdf = new SimpleDateFormat(pattern);

        Date date = null;

        try {
            date = sdf.parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        return date;
    }


}

输出结果如下图所示:

9.Base64

UUID.randomUUID().toString()是javaJDK提供的一个自动生成主键的方法。UUID(Universally Unique Identifier)全局唯一标识符,是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的,是由一个十六位的数字组成,表现出来的形式。

Base64 编码 Encode:

    Base64.getEncoder().encodeToString("hzb".getBytes())  :基本型Base64编码

    Base64.getUrlEncoder().encodeToString("hzb".getBytes())  :URL型Base64编码

    Base64.getMimeEncoder().encodeToString("hzb".getBytes())  :MIME型Base64编码

Base64 解码 Decode:

    Base64.getDecoder().decode(base64EncodingString)  :基本型Base64解码

    Base64.getUrlDecoder().decode(base64EncodingString)  :URL型Base64解码

    Base64.getMimeDecoder().decode(base64EncodingString)  :MIME型Base64解码

import java.io.UnsupportedEncodingException;
import java.util.Base64;
import java.util.UUID;

public class Java8Tester {

    public static void main(String[] args) {

        try {
            String password = "hzb?java8Test";

            //编码使用基本型 base64 编码方案
            String base64EncodingString = Base64.getEncoder().encodeToString(password.getBytes());

            System.out.println("未经过Base64加密的原始密码: " + password);

            System.out.println("  经过Base64加密的加密密码: " + base64EncodingString);

            //解码
            byte[] base64DecodedBytes = Base64.getDecoder().decode(base64EncodingString);

            System.out.println("  经过Base64解密的密码: " + new String(base64DecodedBytes, "utf-8"));

            //编码使用 URL 和文件名安全型 base64 编码方案
            String base64UrlEncodingString = Base64.getUrlEncoder().encodeToString(password.getBytes());

            System.out.println("  经过Base64加密的加密密码(URL): " + base64UrlEncodingString);

            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < 10; i++) {
                sb.append(UUID.randomUUID().toString());
            }

            byte[] sbBytes = sb.toString().getBytes();

            //编码使用 MIME 型 base64 编码方案
            String base64MimeEncodingString = Base64.getMimeEncoder().encodeToString(sbBytes);

            System.out.println("  经过Base64加密的加密密码(MIME): " + base64MimeEncodingString);

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }


    }


}

输出结果如下图所示:

 

Java 8引入了许多新特性,以下是其中一些重要的特性: 1. Lambda表达式:Lambda表达式是Java 8中最重要的特性之一。它允许我们以更简洁的方式编写匿名函数。Lambda表达式可以作为参数传递给方法,或者用于函数式接口的实现。 2. 函数式接口:函数式接口是只包含一个抽象方法的接口。Java 8引入了一些新的函数式接口,如`Predicate`、`Consumer`、`Supplier`和`Function`等。这些接口可以与Lambda表达式一起使用,使得编写函数式代码更加方便。 3. Stream API:Stream API是Java 8中处理集合数据的新方式。它提供了一种流式操作集合的方式,可以进行过滤、映射、排序等操作。Stream API可以大大简化集合数据的处理,并且可以利用多核处理器进行并行操作。 4. 默认方法:默认方法是接口中的一个新特性,它允许在接口中定义具有默认实现的方法。这样一来,当接口的实现类没有实现该方法时,就会使用默认实现。 5. 方法引用:方法引用是一种更简洁地调用已经存在的方法的方式。它可以替代Lambda表达式,使得代码更加简洁易读。 6. 新的日期和时间API:Java 8引入了全新的日期和时间API,取代了旧的`java.util.Date`和`java.util.Calendar`类。新的API提供了更好的日期和时间处理方式,并且支持时区、日历等功能。 7. Optional类:Optional类是一个容器对象,可以包含null或非null的值。它可以避免空指针异常,并且提供了一些便利的方法来处理可能为空的值。 8. 并发增强:Java 8对并发编程进行了一些增强,引入了新的并发工具类,如`CompletableFuture`和`StampedLock`,以及新的并行操作方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值