1.速度更快
没有永久区,MetaSpace 元空间(使用物理内存)会影响垃圾回收机制,提升其效率MetaSpaceSize,MaxMetaSpaceSize
2.代码更少(增加了新的语法Lambda表达式)
Lambda是一个匿名函数,lambda表示式理解为是一段可以传递的代码
匿名内部类:
public void test1(){
Comparator
@override
public int compare(Integer a1,Integer a2){
return Integer.compare(a1,a2);
}
};
TreeSet
}
lambda表达式:
public void test2(){
Comparator
TreeSet
}
1)lambda表达式的基础语法:JDK8中引入了一个新的操作符“->”, 该操作符被称为箭头操作符或lambda操作符
左右遇一括号省
左侧推断类型省
局部内部内:在jdk1.7以前,应用同级别的变量比服饰final修饰
箭头操作符将Lambda表达式拆分成两部分:
左侧:lamda表达式的参数列表
右侧:lambda表达式中所需执行的功能,即lambda体
a.语法格式一:无参数,无返回值
()->System.out.printlin("Hello World"); 例子:Runnable
b.语法格式二:有一个参数,并且没有返回值(若只有一个参数,那么小括号可以省略不写)
(x)->System.out.printlin("x");例子:Consumer
c.语法格式三:有两个以上参数,有返回值,并且lambda体中有多条语句
Comparetor
System.out.println("函数式接口");
return Integer.compare(x,y);
};
d.语法格式四:若Lambda体中只有一条语句,return和大括号都可以省略不写
Comparator
f.语法格式五:Lambda表达式的参数列表的参数类型可以省略不写,因为JVM编译器可以通过上下文推断,数据类型,即:“类型推断”
类型推断:
String[] strs = {"aaa","bbb","ccc"};正确
String[] strs;
strs = {"aaa","bbb","ccc"};错误
List
1.8类型推断进一步升级:
show(new HashMap<>());
pulic void show(Map
2)Lambda表达式需要“函数式接口”的支持
函数式接口:接口中只有一个方法的接口,成为函数式接口。可以使用注解@FunctionalInterface修饰,检查该接口是否只有一个接口
3)Java8 内置的四大核心函数式接口
a.Consumer
void accept(T t);
b.Supplier
T get();
c.Function
R apply(T t);
d. Predicate
Boolean test(T t);
4)方法引用:
若Lambda体中的内容有方法已经实现了,我们可以使用“方法引用”(可以理解为方法引用是Lambda表达式的另外一种表现形式)
主要有三种语法格式:
对象::实例方法名
类::静态方法名
类::实例方法名
注意:
a.Lambda体中调用方法的参数列表与返回值类型,要与函数式接口中抽象方法的函数列表和返回值类型保持一致。
b.若Lambda参数列表中的第一参数是实例方法的调用者,而第二参数是实例方法的参数时,可以使用ClassName::methods
5)构造器引用:
格式:
ClassName::new
注意:需要调用的构造器的参数列表要与函数式接口中抽象方法的参数列表保持一致!
6)数组引用:
Type::new
3.强大的Stream API
Stream是Java8中处理集合的关键抽象概念,他可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。
注意:
1)Stream自己不会存储元素
2)Stream不会改变源对象。相反,他们会返回一个持有结果的新的Stream
3)Stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
Stream操作的三个步骤:
1)创建Stream:一个数据源(如:集合、数组),获取一个流
a.可以通过Collection系列集合提供的Stream()(串行流)或者parallelStream()(并行流)
b.通过Array中的静态方法Stream()获取数组流;
c.通过Stream类中的静态方法of() Stream.of("aa","bb","cc");
d.创建无限流
迭代:Stream.iterate(seed,Function)
生成:Stream.generate(()->Math.random());
2)中间操作:一个中间操作链,对数据源的数据进行处理
a.Stream筛选和切片(中间操作)
filter——接收Lambda,从流中排除某些元素
limit——截断流,使其元素不超过给定数
skip(n)——跳过元素,返回一个扔掉了前n个元素的流,若该流中元素不足n个,则返回一个空流。与limit(n)互补
distinct——筛选,通过流所生成元素的hashCode()和equals去除重复元素。
惰性求值:多个中间操作可以连接起来形成一个流水线,除非流水线上出发终止操作,否则中间操作不会执行任何处理,而在终止操作时一次性全部处理,成为“惰性求值”;
内部迭代:迭代操作由 Stream API完成
b.映射
map——接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素
flatMap——接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。
c.排序
sorted() ——自然排序Comparable
sorted(Comparator com) ——定制排序
3)终止操作(终端操纵):一个终止操作,执行中间操作链,并产生结果。
3)终止操作
a.查找与匹配
allMatch——检查是否匹配所有元素
anyMatch——检查是否至少匹配一个元素
noneMatch——检查是否没有匹配任何元素
findFirst——返回第一个元素
findAny——返回当前流中的任意元素
count——返回流中元素的总个数
max——返回流中的最大值
min——返回流中的最小值
b.归约
reduce(T identity,BinaryOperator) / reduce(BinaryOperator) ——可以将流中元素反复结合起来,得到一个值。
备注:map和reduce的连通通常称为map-reduce模式,因Google 用它来进行网络搜索而出名。
c.收集
collect —— 将流转为其他形式。接收一个Collector接口的实现,用于给Stream中元素做汇总的方法。
获取组函数:summarizingXXX
连接字符串:joining
分区:
employee.stream().colect(Collectors.partitioningBy(e) -> e.getSalary > 8000);
4.便于并行
并行流和串行流(顺序流)
并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。(速度变高了)
Stream API可以声明性地通过parallel()与sequential()在并行流与顺序流之间进行切换。
Fork/Join框架:
就是在必要的情况下,将一个大任务,进行拆分(fork)成若干个小任务(拆到不可再拆时),再将一个个的小任务运算的结果进行join汇报。(JDK1.7)
Fork/Join框架与传统线程池的区别:
a.采用“工作窃取”模式(work-stealing):
当执行新的任务时,它可以将其拆分分成更小的任务执行,并将小任务加到线程队列中,然后再从一个随机线程的队列中头一个并把它放在自己的队列中。
相对于一般的线程池实现,fork/join框架的优势体现在对其中包含的任务的处理方式,在一般的线程池中,如果一个线程正在执行的任务由于某些原因无法继续运行,那么该线程会处于等待状态,而在fork、join框架实现中,如果某个子问题由于等待另一个子问题的完成而无法继续运行,那么处理该子问题的线程会主动寻求其他尚未运行的子问题来执行,这种方式减少了线程的等待时间,提高了性能
5.最大化减少空指针异常Optional
Optional类
Optional
常用方法:
Optional.of(T t):创建一个Optional实例
Optional.empty():创建一个空的Optional实例
Optional.ofNullable(T t):若t不为null,创建Optional实例,否则创建空实例
isPresent():判断是否包含值
orElse(T t):如果调用对象包含值,
6.接口中的默认方法与静态方法
JDK8之前接口只有抽象方法,JDK8之后接口拥有默认方法与抽象类
1)接口的默认方法:修饰符default
2)接口默认方法的“类优先”原则
若一个接口中定义了一个默认方法,而另一个父类活接口中又定义了一个同名的方法时
a)选择父类中的方法。如果一个父类提供了具体的实现,那么接口中具有相同名称和参数的默认方法被忽略。
b)接口冲突。如果一个父接口提供一个默认方法,而另一个接口也提供了一个具有相同名称和参数列表的方法(不管方法是否为默认方法,那么必须覆盖该方法来解决冲突)
7.新时间与日期
LocalDate、LocalTime、LocalDateTime类的实例是不可变的对象,分别表示使用ISO-8601日历系统的日期、时间、日期和时间。他们提供了简单的日期或者时间,并不包含当前的时间信息。也不包含与时区相关的信息。
ISO-8601日历系统是国际标准化组织制定的现代公民的日期和时间的表示法。
Instant:时间戳(以Unix元年:1970年1月1日00:00:00之间的毫秒值)
Instant.now(); //默认获取UTC时区
Duration:计算两个时间之间的间隔
Period:计算两个“日期”之间的间隔
日期的操纵:
TemporalAdjuster:时间校正器。有时我们可能需要获取例如:将日期调整到“下周日”等操作。
TemporalAdjusters:该类通过静态方法提供了大量的常用TemporalAdjuster的实现。
例如:获取下个周日
LocalDate nextSunday = LocalDate.now().with(TemporalAdjusters.next(DayofWeek.SUNDAY));
对时间日期格式化:
DateTimeFormatter :格式化时间、日期
8.重复注解与类型注解
Java8对注解处理提供了两点改进:可重复的注解及可用于类型的注解。
@Repeatable(MyAnnotations.class)