栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java8新特性

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java8新特性

JAVA8学习笔记
  • 速度更快
    • hashmap变化
    • jvm变化
    • 并行流与串行流
      • 一、什么是并行流
      • 二、了解 Fork/Join框架
      • 三、Fork/Join 框架与传统线程池的区别
    • 新时间api
      • 新时间日期API常用、重要对象介绍
      • 新时间日期API日期的操纵
      • 时区的处理
  • 代码更少
    • Lambda表达式
      • 为什么要使用Lambada表达式
      • Lambada表达式实战
      • Lambada表达式的基础语法
        • 语法格式一:无参数,无返回值
        • 语法格式二:有单参数,无返回值
        • 语法格式三:有单参数,小括号可以省略
        • 语法格式四:有多个参数,lambda体中有多条语句
        • 语法格式五:若lambda体中有多条语句,return和大括号可以省略,jvm会进行“类型推断”,否则不行(1.8对类型推断进行了拓展)
      • Lambada需要“函数式接口”的支持
      • java内置的四大核心函数式接口
      • 方法引用
      • 构造器引用
      • 数组引用
    • Stream API
      • 了解Stream
      • Stream的操作步骤
        • 1.创建Stream
        • 2.中间操作
          • 筛选与切片
          • 映射
          • 排序
        • 3.终止操作(终端操作)
          • 查找与匹配
          • 归约
          • 收集
    • Optional类
      • 常用方法列表
    • 接口中的默认方法与静态方法
    • 重复注解与类型注解
      • 一、重复注解与类型注解介绍
      • 二、重复注解与类型注解使用
        • 1、重复注解
        • 2、类型注解

速度更快 hashmap变化

java1.7由于给定的 HashMap 的容量大小是固定的,比如默认初始化:给定的默认容量为 16,负载因子为 0.75。Map 在使用过程中不断的往里面存放数据,当数量达到了 16 * 0.75 = 12 就需要将当前 16 的容量进行扩容,而扩容这个过程涉及到 rehash、复制数据等操作,所以非常消耗性能。因此通常建议能提前预估 HashMap 的大小最好,尽量的减少扩容带来的性能损耗。当 Hash 冲突严重时,在桶上形成的链表会变的越来越长,这样在查询时的效率就会越来越低;时间复杂度为 O(N)。

java1.8在链表的基础上加入红黑树,设置TREEIFY_THRESHOLD 用于判断是否需要将链表转换为红黑树的阈值(红黑树插入效率低,查找删除效率高)

参考链接:https://blog.csdn.net/weixin_44460333/article/details/86770169

jvm变化

将永久代取而代之为元空间,元空间并不在虚拟机中,而是使用本地内存,为什么要这样改进:
1、字符串存在永久代中,容易出现性能问题和内存溢出。
2、类及方法的信息等比较难确定其大小,因此对于永久代的大小指定比较困难,太小容易出现永久代溢出,太大则容易导致老年代溢出。
3、永久代会为 GC 带来不必要的复杂度,并且回收效率偏低。
4、Oracle 可能会将HotSpot 与 JRockit 合二为一。
参考链接:https://blog.csdn.net/weixiang2039/article/details/107102364/

并行流与串行流 一、什么是并行流

并行流 : 就是把一个内容分成多个数据块,并用不同的线程分 别处理每个数据块的流。

Java 8 中将并行进行了优化,我们可以很容易的对数据进行并 行操作。Stream API 可以声明性地通过 parallel() 与 sequential() 在并行流与顺序流之间进行切换。

二、了解 Fork/Join框架

Fork/Join 框架 : 就是在必要的情况下,将一个大任务,进行拆分(fork)成若干个 小任务(拆到不可再拆时),再将一个个的小任务运算的结果进行 join 汇总.

三、Fork/Join 框架与传统线程池的区别

采用 “工作窃取”模式(work-stealing): 当执行新的任务时它可以将其拆分分成更小的任务执行,并将小任务加到线 程队列中,然后再从一个随机线程的队列中偷一个并把它放在自己的队列中。

相对于一般的线程池实现,fork/join框架的优势体现在对其中包含的任务的 处理方式上.在一般的线程池中,如果一个线程正在执行的任务由于某些原因 无法继续运行,那么该线程会处于等待状态。而在fork/join框架实现中,如果 某个子问题由于等待另外一个子问题的完成而无法继续运行.那么处理该子 问题的线程会主动寻找其他尚未运行的子问题来执行。这种方式减少了线程 的等待时间, 高了性能。

深入链接:https://blog.csdn.net/tyrroo/article/details/81390202

新时间api

传统的时间api存在线程安全问题,另外一个不足之处就是代码繁琐,性能低

新时间日期API常用、重要对象介绍

ZoneId: 时区ID,用来确定Instant和LocalDateTime互相转换的规则
Instant: 用来表示时间线上的一个点(瞬时)
LocalDate: 表示没有时区的日期, LocalDate是不可变并且线程安全的
LocalTime: 表示没有时区的时间, LocalTime是不可变并且线程安全的
LocalDateTime: 表示没有时区的日期时间, LocalDateTime是不可变并且线程安全的
Clock: 用于访问当前时刻、日期、时间,用到时区
Duration: 用秒和纳秒表示时间的数量(长短),用于计算两个日期的“时间”间隔

Period: 用于计算两个“日期”间隔

原文链接:https://blog.csdn.net/h_xiao_x/article/details/79729507

新时间日期API日期的操纵


深入链接:https://blog.csdn.net/neweastsun/article/details/88777896

我们可以通过使用lambda表达式,实现TemporalAdjuster 接口自定义TemporalAdjuster 实现。

时区的处理

代码更少 Lambda表达式 为什么要使用Lambada表达式

Lambada表达式实战

匿名内部类使用前:

@Test
    public void test1() {
        Comparator com = new Comparator(){
           @Override
           public int compare(Integer o1, Integer o2) {
               return Integer.compare(o1,o2);
           }
       };
    }

匿名内部类使用后:

@Test
    public void Test2() {
        Comparator com = (x,y) -> Integer.compare(x,y);
    }

遍历使用前:

 for (String str : list) {
            System.out.println(str);
        }

遍历使用后:

  list.forEach(System.out::println);
Lambada表达式的基础语法

语法格式一:无参数,无返回值
Runnable a = () -> System.out.println("Hello");
        a.run();
语法格式二:有单参数,无返回值
Consumer con = (x) -> System.out.println(x);
        con.accept("Hello");
语法格式三:有单参数,小括号可以省略
 Consumer con = x -> System.out.println(x);
        con.accept("Hello");
语法格式四:有多个参数,lambda体中有多条语句
 Comparator com = (x, y) -> {
            System.out.println("hello");
            return Integer.compare(x, y);
        };
语法格式五:若lambda体中有多条语句,return和大括号可以省略,jvm会进行“类型推断”,否则不行(1.8对类型推断进行了拓展)
 Runnable a = () -> System.out.println("Hello");
        a.run();
Lambada需要“函数式接口”的支持

只能出现一个抽象方法

java内置的四大核心函数式接口

需要自己实现,只提供接口

方法引用

若Lambda体中的内容有方法已经实现了,我们可以使用“方法引用”(可以理解为Lambda表达式的另一种表现形式)
主要有三种语法形式
参考链接:https://blog.csdn.net/jeddzd/article/details/91973

注意事项

构造器引用

多个构造函数根据参数数量匹配构造器

数组引用


Stream API 了解Stream

Stream的操作步骤 1.创建Stream

1.可以通过Collection系列集合提供的strean()或parallelStream()

2.通过Arrays中的静态方法stream()获取数组流

3.通过Stream类中的静态方法of()

4.创建无限流
迭代

生成

2.中间操作 筛选与切片


中间操作只有在终止操作执行才执行

映射


Stream.flatMap,正如它的名称所猜测的,是map和一个flat行动。这意味着您首先对元素应用一个函数,然后将其扁平化。Stream.map只对流应用函数,而不对流进行平坦处理。
为了理解什么是扁平化,考虑一个像[[1,2,3],[4,5,6],[7,8,9]]这样的具有“两个层次”的结构。 扁平化意味着将其转化为“一个一级”结构:[1,2,3,4,5,6,7,8,9]。

类似于add()和addAll()

排序

3.终止操作(终端操作)

查找与匹配 归约

收集



常用Lambda表达式
https://blog.csdn.net/LuQiaoYa/article/details/113249503

Optional类 常用方法列表


学习链接:https://www.jianshu.com/p/58b3f09a3429

接口中的默认方法与静态方法

大家都知道接口是用来对代码进行一种规范,对代码进行一种规范,实际开发中大多是协作开发,所以这就需要一种规范,大家都按照这种规范对代码进行书写,那么就会在整合的时候,非常的轻松了。

   然而,有些时候会出现一个问题就是:当有多个类实现了相同的接口,接口中的某一些方法的实现体可能都是一样的时候,这样无疑浪费了很多时间,在写重复的代码,或者说copy。

  应对于这种情况,Java8在接口中为我们新增了default和static方法,这两种方法可以有方法体。

原文链接:https://blog.csdn.net/weixin_42047611/article/details/81453841

 public interface Compute {
    
    int sub(int x,int y);
 
    default void ComputeDefault(){
        System.out.println("Compute的default方法。");
    }
 
    static void ComputeStatic(){
        System.out.println("Compute的static方法。");
    }
}

接口中的默认方法,即default方法可以被继承或者实现,而静态方法,即static修饰的有方法体的方法不会被继承或实现

重复注解与类型注解 一、重复注解与类型注解介绍

Java 8对注解处理提供了两点改进:可重复的注解及可用于类型的注解。
  重复注解:使用@Repeatable元注解,参数为可重复注解的容器,重复注解可以在目标上重复使用
  类型注解:java8中为ElementType新增了两个枚举值:TYPE_PARAMETER和TYPE_USE

二、重复注解与类型注解使用 1、重复注解

即可以在同一方法、属性、类等类型中多次使用同一个注解。此特性相当于对JAVA8之前的重复注解在编译层面的增强,JAVA8实现此特性主要依赖于@Repeatable注解。

JAVA8之前的写法
定义一个重复注解:

@interface MyRepAnno{
     String value();
 }
 @interface MyRepAnnos{
     MyRepAnno[] value();
 }

使用此注解:

 @MyRepAnnos({@MyRepAnno(""),@MyRepAnno("")})
class TestMyClass{}

JAVA8中的写法
定义一个重复注解

 @Repeatable(MyRepAnnos.class)
 @interface MyRepAnno{
     String value();
 }
 @interface MyRepAnnos{
     MyRepAnno[] value();
 }

使用此注解:

@MyRepAnno("")
 @MyRepAnno("")
 class TestMyClass{}

上面例子中发现JAVA8中定义重复注解与JAVA7相比只是多了个@Repeatable,使用重复注解的地方JAVA8则比之前的写法更简单方便,可读性更强。

2、类型注解

TYPE_PARAMETER
表示该注解能使用在自定义类型参数(参数的自定义类型可以是javaBean或者枚举等)的声明语句中。例子如下:

先声明个使用TYPE_PARAMETER参数的自定义注解@MyAnno

@Target({ElementType.TYPE_PARAMETER})
 @interface MyAnno{}

定义一个方法使用自定义类型MyClass

 public String getMyClassInfo(MyClass cls){
     return null;
 }

下面语句则是在自定义类型MyClass的声明使用了@MyAnno注解

 class  MyClass<@myAnno String>{}

TYPE_USE
表示该注解能使用在使用类型的任意语句中。

先定义一个自定义注解:

 @Target({ElementType.TYPE_USE})
@interface MyAnnoUse{}

下面演示四种情形:

创建实例时使用

MyClass aClass = new @MyAnnoUse MyClass<>();

类型强转时使用

 Object o = "test";
 String str = (@MyAnnoUse String) o;

方法形参中使用

 public String getUser(@MyAnnoUse String  name, Integer age){
     return null;
 }

泛型中使用

 public String getClasses(List<@MyAnnoUse User> list){
     return null;
 }
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/344750.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号