视频讲解
A.改变
- 8以后底层的方法区也称为永久区被从堆中剥离出来形成了另外一个元空间Metaspace的概念,其是使用的物理内存,即电脑的运行内存,只有要满了的时候,才会被垃圾回收器回收。但概率低。
- 增强hashMap,添加红黑树,除了添加意外,其余属性均提高。
00 Lambda表达式
A . 定义
Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。使用 Lambda 表达式可以使代码变的更加简洁紧凑。
B .重要特征:
- 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
- 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
- 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
- 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定表达式返回了一个数值。


C .使用范围
一般针对的是只有一个方法的接口,或者是一个匿名内部类的使用来进行达到简写的目的。
使用 Lambda 表达式需要注意以下两点:
-
Lambda 表达式主要用来定义行内执行的方法类型接口.
-
Lambda 表达式免去了使用匿名方法的麻烦,并且给予Java简单但是强大的函数化的编程能力。
D .语法格式
一个 lambda 表达式包含以下内容:
-
箭头左侧是参数。括号中以逗号分隔的形式参数列表。该
CheckPerson.test方法包含一个参数 ,p它代表Person类的一个实例 。注意:您可以省略 lambda 表达式中参数的数据类型。另外,如果只有一个参数,可以省略括号。例如,以下 lambda 表达式也是有效的:
p -> p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25 -
箭头标记,
-> -
右侧是方法实现。主体,由单个表达式或语句块组成。此示例使用以下表达式:
p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25如果指定单个表达式,则 Java 运行时会计算该表达式,然后返回其值。或者,您可以使用 return 语句:
p -> { return p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25; }return 语句不是表达式;在 lambda 表达式中,您必须将语句括在大括号 (
{}) 中。但是,您不必将 void 方法调用括在大括号中。例如,以下是有效的 lambda 表达式:电子邮件 -> System.out.println(email)
请注意,一个 lambda 表达式看起来很像一个方法声明;您可以将 lambda 表达式视为匿名方法——没有名称的方法。
下面的示例 Calculator是一个采用多个形参的 lambda 表达式示例:
公共类计算器 {
interface IntegerMath {
int operation(int a, int b);
}
public int operationBinary(int a, int b, IntegerMath op) {
return op.operation(a, b);
}
public static void main(String... args) {
Calculator myApp = new Calculator();
IntegerMath 加法 = (a, b) -> a + b;
IntegerMath 减法 = (a, b) -> a - b;
System.out.println("40 + 2 = " +
myApp.operateBinary(40, 2, add));
System.out.println("20 - 10 = " +
myApp.operateBinary(20, 10, 减法));
}
}
该方法operateBinary对两个整数操作数执行数学运算。操作本身由 的实例指定IntegerMath。该示例使用 lambda 表达式定义了两个操作,addition并且subtraction. 该示例打印以下内容:
40 + 2 = 42
20 - 10 = 10
E .变量作用域(注意事项)
lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。我们也可以直接在 lambda 表达式中访问外层的局部变量:
lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义)
int num = 1;
Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num));
s.convert(2);
num = 5;
//报错信息:Local variable num defined in an enclosing scope must be final or effectively
在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量。
String first = "";
Comparator<String> comparator = (first, second) -> Integer.compare(first.length(), second.length()); //编译会出错
01 方法引用(:😃
其就是对lambda表达式的简写。被用作方法的引用。使用lambda表达式会创建匿名方法,但是有时候需要一个lambda表达式只用于调用一个已经存在的方法,在此才有了方法引用。方法引用通过方法的名字来指向一个方法。方法引用可以使语言的构造更紧凑简洁,减少冗余代码。方法引用使用一对冒号 :: 。



A. 静态方法的引用(static method)
类名::静态方法名
public class Demo {
@Test
public void test() {
List<String> list = Arrays.asList("aaaa", "bbbb", "cccc");
//静态方法语法 ClassName::methodName
list.forEach(Demo::print);
}
public static void print(String content){
System.out.println(content);
}
}
B. 对象的实例方法引用。
对象::实例方法名
public class Demo {
@Test
public void test() {
List<String> list = Arrays.asList("aaaa", "bbbb", "cccc");
//静态方法语法 ClassName::methodName
list.forEach(new Demo()::print);
}
public void print(String content){
System.out.println(content);
}
}
C. 对象的超类方法引用
public class Example extends BaseExample{
@Test
public void test() {
List<String> list = Arrays.asList("aaaa", "bbbb", "cccc");
//对象的超类方法语法: super::methodName
list.forEach(super::print);
}
}
class BaseExample {
public void print(String content){
System.out.println(content);
}
}
D. 类构造器引用
注:需要调用的构造器的参数列表要与函数式接口中抽象方法的参数列表保持一致!!!
public class Example {
@Test
public void test() {
//无参构造器
InterfaceExample com = Example::new;
Example bean = com.create();
Example bean = com.create("STRING");
System.out.println(bean);
}
}
interface InterfaceExample{
//不带参数
Example create();
//带参数
Example create();
}
E. 数组构造器引用
public class Example {
public static void main(String[] args) {
Function <Integer, Example[]> function = Example[]::new;
Example[] array = function.apply(4); //这里的4是数组的大小
for(Example e:array){
System.out.println(e); //如果输出的话,你会发现会输出4个空对象(null)
}
}
}
03 函数式接口
A. 定义
函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。函数式接口可以被隐式转换为 lambda 表达式。Lambda 表达式和方法引用(实际上也可认为是Lambda表达式)上。
B. 四大内置核心函数式接口
-
Consumer
:消费型接口。void accept(T t); -
Supplier
:供给型接口。 T get(); -
Function<T,R>:函数型接口。R apply(T t);
-
Predicate
:断言型接口。boolean test(T t);
04 Stream API
注意
- 对数据源进行流操作时,产生的是新的流对象,原来的数据源不改变。
- 自己不会存储元素
- 其操作是延迟执行的,这意味着他们会等到需要结果的时候执行。
- 中间操作map和flatMap的过程步骤和add与addAll类似。

A . 定义
流是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列集合讲的是数据,流讲的是计算
B.操作步骤

C. 创建流

D.中间操作



- Map

flatMap:将多个流中的转换为一个流,即平铺流,形成一条流。

排序:

E. 终止操作

F. 归约reduce
- 定义:可以将流中元素反复结合起来,得到一个值,相当与Map Reducer,map用于拆分计算,reducer用于进行整合并得出一个总的结果。

G. 收集collect
- 定义:将流转换为其他形式。接收一个Conllector接口的实现,用于给Stream中元素做汇总的方法。其中Collectors实用类提供了许多静态方法,可以方便地创建常见收集器实例。
H.并行流与顺序流
以往写的流均是以顺序流的形式来进行的。可以通过parallel()切换为并行流与sequential()切换为穿行流来在并行流和顺序流之间进行切换。
- 并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流,上述两个方法底层使用fork join框架。
05 Optional容器类

06 接口中的默认方法和静态方法
- 接口中可以对方法进行实现,以及声明为默认方法,其实现此接口的均会执行默认方法。

07 新时间日期API

A.标准日期格式
本地时间:LocalDateTime对应的方法,plus添加、minus减少、get获取。均可进行对年月日时分秒的具体操作。
B.时间戳格式
Instant:时间戳(以Unix 元年:1970.1.1到某个时间的毫秒值)。计算机读的就是时间戳。
- atOffset:设置偏移量
- toEpochMilli:转换为毫秒

C.日期计算间隔
-
Duration:计算两个“时间”之间的间隔。在其下有个between方法计算。
-
Period:计算两个“日期”之间的间隔。同理
D.时间校正器TemporalAdjuster接口中有TemporalAdjusters静态类
- 意义:有时我们可能需要获取例如:将日期调整到“下个周日”等操作。

E. 格式化时间/日期DateTimeFormatter
- 自定义日期格式
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
LocalDateTime ldt = LocalDateTime.now();
string strDate = ldt.format(dtf);

F. 时区设置
ZonedDate、ZonedTime、ZonedDateTime.

浙公网安备 33010602011771号