Java 8

是oracle公司于2014年3月发布,可以看成是自Java 5 以来最具革命性的版本。Java 8为Java语言、编译器、类库、开发工具与JVM带来了大量新特性。

新特性简介

  • 代码更少(增加了新的语法:Lambda 表达式)
  • 函数式接口 (接口上使用 @FunctionalInterface )
  • 强大的 Stream API 集合讲的是数据,Stream讲的是计算!
  • 速度更快
  • 最大化减少空指针异常:Optional
  • Nashorn引擎,允许在JVM上运行JS应用
  • 便于并行
  • 为接口添加静态方法和默认方法
  • 新时间日期API
  • Optional类的使用

新时间日期API

LocalDateTime currentTime = LocalDateTime.now();
    // 获取当前年月日
    LocalDate localDate = LocalDateTime.now().toLocalDate();
    // 获取最后一天的最小时间
    LocalDateTime minTime = LocalDateTime.of(localDate.with(TemporalAdjusters.lastDayOfMonth()), LocalTime.MIN);
    // 获取最后一天的最大时间
    LocalDateTime maxTime = LocalDateTime.of(localDate.with(TemporalAdjusters.lastDayOfMonth()), LocalTime.MAX);

SimpleDateFormat线程安全问题

    /**
     * 执行会报异常:
     *   java.util.concurrent.ExecutionException: java.lang.NumberFormatException: For input string: "E.21121"
     */
    @Test
    public void test() throws ExecutionException, InterruptedException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Callable<Date> callable = new Callable<Date>() {
            @Override
            public Date call() throws Exception {
                return sdf.parse("2020-11-12");
            }
        };

        List<Future<Date>> futureList = new ArrayList<>();
        ExecutorService pool = Executors.newFixedThreadPool(10);
        try {
            for (int i = 0; i < 10; i++) {
                futureList.add(pool.submit(callable));
            }
            for (Future<Date> dateFuture : futureList) {
                System.out.println(dateFuture.get());
            }
        } finally {
            pool.shutdown();
        }
    }

date time

统计操作耗时/方法计时/方法耗时

Instant start = Instant.now();
...
Instant end = Instant.now();
System.out.println(Duration.between(start, end).toMillis());
// 将java.util.Date 转换为java8 的java.time.LocalDateTime,默认时区为东8区
public static LocalDateTime dateConvertToLocalDateTime(Date date) {
    return date.toInstant().atOffset(ZoneOffset.of("+8")).toLocalDateTime();
}
//将java8 的 java.time.LocalDateTime 转换为 java.util.Date,默认时区为东8区
public static Date localDateTimeConvertToDate(LocalDateTime localDateTime) {
    return Date.from(localDateTime.toInstant(ZoneOffset.of("+8")));
}

Instant:时间戳,相当于java.util的Date
LocalDate:只包含日期,比如:2016-10-20
LocalTime:只包含时间,比如:23:12:10
LocalDateTime:包含日期和时间,比如:2016-10-20 23:14:21
Duration:计算两个“时间”的间隔
Period:用于计算两个“日期”的间隔
ZoneOffset:时区偏移量,比如:+8:00
ZonedDateTime:可以得到特定时区的日期/时间
Clock:时钟,比如获取目前美国纽约的时间

of:静态工厂方法(用类名去调用)。
parse:静态工厂方法,关注于解析(用类名去调用)。
now: 静态工厂方法,用当前时间创建实例(用类名去调用)
get:获取某些东西的值。
is:检查某些东西的是否是true。
with:返回一个部分状态改变了的时间日期对象拷贝(单独一个with方法,参数为TemporalAdjusters类型)。
plus:返回一个时间增加了的、时间日期对象拷贝(如果参数是负数也能够有minus方法的效果)。
minus:返回一个时间减少了的、时间日期对象拷贝。
to:把当前时间日期对象转换成另外一个,可能会损失部分状态。
at:把这个对象与另一个对象组合起来,例如: date.atTime(time)。
format :根据某一个DateTimeFormatter格式化为字符串。

@Test
public void getRepeatDataInList() {
    Stream<Integer> integerStream = Stream.of(1, 1, 2, 2, 3, 4, 5);
    Map<Integer, Long> intWithCountMap =
        integerStream.collect(Collectors.groupingBy(p -> p, Collectors.counting()));
    System.out.println(intWithCountMap);
    List<Integer> repeatedNumber = intWithCountMap.entrySet().stream()
            .filter(e -> e.getValue() > 1L)
            .map(Map.Entry::getKey)
            .collect(Collectors.toList());
    System.out.println(repeatedNumber);
    List<Integer> notRepeatedNumber = intWithCountMap.entrySet().stream()
            .filter(e -> e.getValue() == 1L)
            .map(Map.Entry::getKey)
            .collect(Collectors.toList());
    System.out.println(notRepeatedNumber);
}

ArrayList 源码分析:
jdk7:
ArrayList list = new ArrayList();//初始化一个长度为10的Object[] elementData
sysout(list.size());//返回存储的元素的个数:0
list.add(123);
list.add(345);

当添加第11个元素时,需要扩容,默认扩容为原来的1.5倍。还需要将原有数组中的数据复制到新的数组中。
删除操作:如果删除某一个数组位置的元素,需要其后面的元素依次前移。
remove(Object obj) / remove(int index)
jdk8:
ArrayList list = new ArrayList();//初始化一个长度为0的Object[] elementData
sysout(list.size());//返回存储的元素的个数:0
list.add(123);//此时才创建一个长度为10的Object[] elementData
list.add(345);

当添加第11个元素时,需要扩容,默认扩容为原来的1.5倍。还需要将原有数组中的数据复制到新的数组中。
开发时的启示:

  1. 建议使用:ArrayList list = new ArrayList(int length);
  2. jdk8延迟了底层数组的创建:内存的使用率;对象的创建更快

lambda

  • Consumer Supplier Function Predicate
@FunctionalInterface
public interface Consumer<T> {
    /**
     * Performs this operation on the given argument.
     */
    void accept(T t);
}
@FunctionalInterface
public interface Supplier<T> {
    /**
     * Gets a result.
     * @return a result
     */
    T get();
}
@FunctionalInterface
public interface Function<T, R> {
    /**
     * Applies this function to the given argument.
     * @param t the function argument
     * @return the function result
     */
    R apply(T t);
@FunctionalInterface
public interface Predicate<T> {
    /**
     * Evaluates this predicate on the given argument.
     * @param t the input argument
     * @return {@code true} if the input argument matches the predicate,
     * otherwise {@code false}
     */
    boolean test(T t);
  • 其它接口:BiFunction UnaryOperator BinaryOperator BiConsumer BiPredicate ToIntFunction ToLongFunction ToDoubleFunction IntFunction LongFunction DoubleFunction
作者:张三  创建时间:2022-04-19 16:06
最后编辑:张三  更新时间:2023-07-06 11:34