基础-java8新特性

1、性能提升

  1. jdk1.7以前,方法区通过永久代来实现。jdk1.8后,方法区通过元空间(MetaSpace)来实现,而元空间是本地内存。
  2. 哈希表中,当一个桶中的元素个数超过8(======),会将链表转化为红黑树。

2、Lambda表达式

学习lambda表达式之前,先了解一下匿名匿名内部类。

2.1 匿名内部类

这是有关内部类的讲解

对于匿名内部类,它是一个表达式,最后用 ; 结尾,主体是一对大括号,里面编写代码逻辑。匿名内部类有父类,或者有接口。一般是用于 这个实例只使用一次,为了简洁,就不要为它再创建一个类,直接使用匿名内部类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class TestLambda {

public void test1(){

//匿名内部类写法
//Comparator是一个接口
Comparator<Integer> comparator = new Comparator<Integer>() {
@Override
public int compare(Integer t1, Integer t2) {
return Integer.compare(t1,t2);
}
};

//lambda表达式
Comparator<Integer> comparator1 = ((t1,t2) -> Integer.compare(t1,t2));
}
}

2.2 Lambda表达式

基础语法:java8中引入了一个新的操作符->,该操作符称为箭头操作符或lambda操作符。

箭头操作符将lambda表达式拆分成两个部分,左侧是lambda表达式的参数列表,如果是接口,即是接口中抽象方法的参数列表,右侧是lambda表达式中所需执行的功能,lambda体,即对该抽象方法的具体实现。


语法格式一:抽象方法无参数,无返回值。

() -> System.out.println("hello!");

1
2
3
4
5
6
7
8
9
10
11
12
public void test2(){
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("hello world!");
}
};
runnable.run();
//=======================================
Runnable runnable1 = () -> System.out.println("hello world!");
runnable1.run();
}

语法格式二:有一个参数,无返回值

(x) -> System.out.println(x);

1
2
3
4
5
6
7
8
9
public void test3(){
//实现accept这个抽象方法
Consumer<String> con = (x) -> System.out.println(x);
con.accept("hello world!");
}

public interface Consumer<T> {
void accept(T var1);
}

语法格式三:如果只有一个参数,小括号可以不写(不过一般都写)

语法格式四:有两个以上参数,有返回值,并且lambda体中有多条语句,则语句写在大括号中

1
2
3
4
Comparator<Integer> comparator1 = ((t1,t2) -> {
System.out.println("hahah");
return Integer.compare(t1,t2);
});

语法格式五:有两个以上参数,有返回值,如果只有一条语句,则大括号和return都可以省略不写

Comparator<Integer> comparator1 = ((t1,t2) -> Integer.compare(t1,t2));

语法格式六:lambda表达式的参数列表的数据类型可以省略不写,因为jvm编译器通过上下文可以推断出超参数的数据类型(通过前面泛型推断)

Comparator<Integer> comparator1 = ((Integer t1,Integer t2) -> Integer.compare(t1,t2));


lambda表达式需要“函数式接口”的支持。函数式接口即接口中只能有一个抽象方法的接口。可以使用注解@FunctionalInterface修饰,表明这个接口必须是函数式接口


使用lambda表达式的例子:(利用设计模式中的策略模式)

1
2
3
4
5
6
7
8
9
10
11
12
13
public void test4(){
Integer res = get(2,(x) -> x * x);
//4
System.out.println(res);
}

public Integer get(Integer num,Operation operation){
return operation.getValue(num);
}

public interface Operation{
Integer getValue(Integer num);
}

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

  1. Consumer 消费型接口

    void accpet(T t);

  2. Supplier 供给型接口

    T get();

  3. Function<T,R> 函数型接口

    R apply(T t);

  4. Predicate 断言型接口

    boolean test(T t);

还有他们的子类接口也可以使用

2.4 方法引用

为了更加简化lambda表达式。

方法引用是什么? 若lambda体中的内容有方法已经实现了,我们可以使用”方法引用”,可以理解为方法引用是lambda表达式的另外一种表现形式。

【注意事项】1、使用的前提是lambda体中方法的参数列表和返回值类型要与函数式接口中抽象方法的参数列表和返回值类型保持一致。 2、若lambda参数列表的第一参数是实例方法的调用者,而第二参数是实例方法的参数时,可以使用类::实例方法名

分为:类::静态方法名 对象::实例方法名 类::实例方法名

2.5 构造器引用

类名::new

构造器的参数列表和函数式接口中抽象方法的列表中参数个数是一致的。比如抽象方法的参数个数是0个,那就默认匹配类的无参构造器。

2.6 数组引用

Type::new

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public void test5(){
//对象::实例方法
Consumer<Integer> com = (x) -> System.out.println(x);
Consumer<Integer> com1 = System.out::println;

Employee employee = new Employee();
Supplier<String> sup = () -> employee.getName();
System.out.println(sup.get());

Supplier<String> sup1 = employee::getName;
System.out.println(sup.get());

//类::静态方法名
Comparator<Integer> com3 = (x,y) -> Integer.compare(x,y);
Comparator<Integer> com4 = Integer::compareTo;

//类::实例方法名
BiPredicate<String,String> bp = (x,y) -> x.equals(y);
BiPredicate<String,String> bp1 = String::equals;

//构造器引用
//类::new
Supplier<Employee> employeeSupplier = Employee::new;

//数组引用
Function<Integer,String[]> fun = (x) -> new String[x];
String[] strings = fun.apply(10);
System.out.println(strings.length);

Function<Integer,String[]> function = String[]::new;

}

3、StreamAPI

【流】是数据渠道,用于操作数据源(数组、集合等)所生成的元素序列。

  • Stream自己不会存储元素
  • Stream不会改变源对象,而是返回一个全新的流
  • Stream操作时延迟执行的,它们会等到需要结果时才执行

流操作的三个步骤:

3.1 创建Stream

  1. 通过Collection系列集合提供的stream()或者parallelStream()

3.2 Stream的筛选与切片

(1)filter

1
Stream<T> filter(Predicate<? super T> predicate);

filter()参数内需要传一个断言型lambda表达式,即传一个参数,返回一个boolean类型的值。

1
2
3
4
List<String> list = new ArrayList<>();
list.stream()
.filter((x) -> x.isBlank())
.forEach(System.out::println);

(2)limit

一旦发现满足条件的两个数据,其他后序的迭代操作就不再继续进行了。

(3)skip、distinct()

3.3 映射

(1)map

1
<R> Stream<R> map(Function<? super T, ? extends R> mapper);

map接收一个函数型接口(即一个函数),即传进去一个参数,返回一个值,也可以直接传一个函数。即依次取出集合中的每个元素,然后对这个元素应用到函数上。

(2)flatMap

如果接收的每个元素都是一个流的话,flatMap可以把流中的每个元素统一添加到一个流中。而map的话是把这个流直接加到一个统一的流中。

4、排序

5、查找与匹配

6、归约与查找

(1)归约

(2)收集

将结果收集到特定集合中

对数据进行求和

分组

多级分组

分区

只有true和false区

4、Optional类

Optional< T >类是一个容器类,代表一个值存在或者不存在,原来用null表示一个值不存在,现在Optional可以更好的表达这个概念。并且可以避免空指针异常。

5、接口中的默认方法和静态方法

1
2
3
4
5
6
7
8
9
10
public interface practiceInterface {

default String test(){
return "haha";
}

static String test2(){
return "hehe";
}
}

基础-java8新特性
https://vickkkyz.fun/2022/10/18/Java/JavaSE/java8新特性/
作者
Vickkkyz
发布于
2022年10月18日
许可协议