- 速度更快
- 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、类型注解
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 汇总.
采用 “工作窃取”模式(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语法格式四:有多个参数,lambda体中有多条语句con = x -> System.out.println(x); con.accept("Hello");
Comparator语法格式五:若lambda体中有多条语句,return和大括号可以省略,jvm会进行“类型推断”,否则不行(1.8对类型推断进行了拓展)com = (x, y) -> { System.out.println("hello"); return Integer.compare(x, y); };
Runnable a = () -> System.out.println("Hello");
a.run();
Lambada需要“函数式接口”的支持
只能出现一个抽象方法
需要自己实现,只提供接口
若Lambda体中的内容有方法已经实现了,我们可以使用“方法引用”(可以理解为Lambda表达式的另一种表现形式)
主要有三种语法形式
参考链接:https://blog.csdn.net/jeddzd/article/details/91973
注意事项
多个构造函数根据参数数量匹配构造器
1.可以通过Collection系列集合提供的strean()或parallelStream()
2.通过Arrays中的静态方法stream()获取数组流
3.通过Stream类中的静态方法of()
4.创建无限流
迭代
生成
中间操作只有在终止操作执行才执行
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
学习链接: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
即可以在同一方法、属性、类等类型中多次使用同一个注解。此特性相当于对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{}
下面演示四种情形:
创建实例时使用
MyClassaClass = 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;
}



