Java8 新特性

1、函数式接口

函数式接口(Function Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。函数式接口可以被隐式的转换为Lambda表达式。

定义一个函数式接口如下:

@FunctionalInterface
interface GreetingService {
    void sayMessage(String message);
}

JDK1.8 新增加的函数式接口:

  • java.util.function

java.util.function它包含了很多类,用来支持Java的函数式编程,该包中的函数式接口有:

序号

接口

Lambda表达式

描述

1

BiConsumer 

(T,U) ->{}

代表了一个接受两个输入参数的操作,并且不返回任何结果

2

BiFunction

(T,U)->{R}

代表了一个接受两个输入参数的方法,并且返回一个结果

3

BinaryOperator

(T,T)->{T}

代表了一个作用于两个同类型操作符的操作,并且返回了操作符同类型的结果

4

BiPredicate

(T,U)->{boolean}

代表了一个接收两个参数并且返回boolean值方法

5

BooleanSupplier

()->{boolean}

代表了boolean值结果的提供方

6

Consumer

(T)->{}

代表了接受一个输入参数并且无返回的操作

7

DoubleBinaryOperator

(double,double)->{double}

代表了作用于两个double值操作符的操作,并且返回了一个double值的结果。

8

DoubleConsumer

(double)->{}

代表一个接受double值参数的操作,并且不返回结果。

9

DoubleFunction

(double)->{R}

代表接受一个double值参数的方法,并且返回结果

10

DoublePredicate

(double)->{boolean}

代表一个拥有double值参数的boolean值方法

11

DoubleSupplier

()->{double}

代表一个double值结构的提供方

12

DoubleToIntFunction

(double)->{int}

接受一个double类型输入,返回一个int类型结果

13

DoubleToLongFunction

(double)->{long}

接受一个double类型输入,返回一个long类型结果

14

DoubleUnaryOperator

(double)->{double}

接受一个参数同为类型double,返回值类型也为double

15

Function

(T)->{R}

接受一个输入参数,返回一个结果。

16

IntBinaryOperator

(int,int)->{int}

接受两个参数同为类型int,返回值类型也为int 。

17

IntConsumer

(int)->{}

接受一个int类型的输入参数,无返回值 。

18

IntFunction

(int)->{R}

接受一个int类型输入参数,返回一个结果 。

19

IntPredicate

(int)->{boolean}

接受一个int输入参数,返回一个布尔值的结果。

20

IntSupplier

()->{int}

无参数,返回一个int类型结果。

21

IntToDoubleFunction

(int)->{double}

接受一个int类型输入,返回一个double类型结果 。

22

IntToLongFunction

(int)->{long}

接受一个int类型输入,返回一个long类型结果。

23

IntUnaryOperator

(int)->{int}

接受一个参数同为类型int,返回值类型也为int 。

24

LongBinaryOperator

(long,long)->{long}

接受两个参数同为类型long,返回值类型也为long。

25

LongConsumer

(long)->{}

接受一个long类型的输入参数,无返回值。

26

LongFunction

(long)->{R}

接受一个long类型输入参数,返回一个结果。

27

LongPredicate

(long)->{boolean}

接受一个long输入参数,返回一个布尔值类型结果。

28

LongSupplier

()->{long}

无参数,返回一个结果long类型的值。

29

LongToDoubleFunction

(long)->{double}

接受一个long类型输入,返回一个double类型结果。

30

LongToIntFunction

(long)->{int}

接受一个long类型输入,返回一个int类型结果。

31

LongUnaryOperator

(long)->{long}

接受一个参数同为类型long,返回值类型也为long。

32

ObjDoubleConsumer

(Object,double)->{}

接受一个object类型和一个double类型的输入参数,无返回值。

33

ObjIntConsumer

(Object,int)->{}

接受一个object类型和一个int类型的输入参数,无返回值。

34

ObjLongConsumer

(Object,long)->{}

接受一个object类型和一个long类型的输入参数,无返回值。

35

Predicate

(T)->{boolean}

接受一个输入参数,返回一个布尔值结果。

36

Supplier

()->{T}

无参数,返回一个结果。

37

ToDoubleBiFunction

(T,U)->{dobule}

接受两个输入参数,返回一个double类型结果

38

ToDoubleFunction

(T)->{double}

接受一个输入参数,返回一个double类型结果

39

ToIntBiFunction

(T,U)->{int}

接受两个输入参数,返回一个int类型结果。

40

ToIntFunction

(int)->{int}

接受一个输入参数,返回一个int类型结果。

41

ToLongBiFunction

(T,U)->{long}

接受两个输入参数,返回一个long类型结果。

42

ToLongFunction

(T)->{long}

接受一个输入参数,返回一个long类型结果。

43

UnaryOperator

(T)->{T}

接受一个参数为类型T,返回值类型也为T。

 2、Lambda表达式

Lambda表达式,也可称为闭包,它是推动Java8 发布的最重要的新特征,Lambda允许把函数作为一个方法的参数传递进方法中。使用Lambda表达式可以使代码变的更加简洁紧凑。

Lambda表达式的语法格式如下:

(parameters) -> expression 
或 
(parameters) ->{ statements; }

以下是Lambda表达式的重要特征:

  • 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
  • 可选的参数圆括号:一个参数无需定义括号,但多个参数需要定义圆括号。
  • 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
  • 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定表达式返回值。

Lambda表达式的简单例子:

// 1. 不需要参数,返回值为 5  
() -> 5  
  
// 2. 接收一个参数(数字类型),返回其2倍的值  
x -> 2 * x  
  
// 3. 接受2个参数(数字),并返回他们的差值  
(x, y) -> x – y  
  
// 4. 接收2个int型整数,返回他们的和  
(int x, int y) -> x + y  
  
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
(String s) -> System.out.print(s)

3、方法引用

在Java8 中,方法引用是一种简化Lambda表达式的语法。它允许通过方法的名称来直接引用一个已经存在的方法,而不是像Lambda表达式那样定义个匿名函数。方法引用使代码更加简洁易读,而且可以提高代码的可维护性。

Java8 中共有四种方法引用的形式:

1.静态方法引用:ClassName::staticMethodName

// Lambda表达式写法
Function parseIntLambda = str -> Integer.parseInt(str);

// 方法引用写法
Function parseIntReference = Integer::parseInt;

2.实例方法引用:instance::instanceMethodName

// Lambda表达式写法
BiPredicate startsWithLambda = (str, prefix) -> str.startsWith(prefix);

// 方法引用写法
BiPredicate startsWithReference = String::startsWith;

3.对象方法引用:ClassName::instanceMethodName

List names = Arrays.asList("Alice", "Bob", "Charlie");

// Lambda表达式写法
names.forEach(str -> System.out.println(str));

// 方法引用写法
names.forEach(System.out::println);

4.构造方法引用:ClassName::new

// Lambda表达式写法
Supplier> listSupplierLambda = () -> new ArrayList<>();

// 方法引用写法
Supplier> listSupplierReference = ArrayList::new;

4、Stream

Stream是一个功能强大的用于处理集合数据的工具。Stream API提供了一种更简洁、更易读的方式来操作集合,使得数据处理更具有函数式编程风格。

下面是Java8 Stream的基本用法和一些常用操作:

1、创建Stream:

  • 从集合创建:List list = Arrays.asList("a", "b", "c"); Stream stream = list.stream();
  • 从数组创建:Stream stream = Stream.of("a", "b", "c");
  • 使用Stream.of()创建单个元素的Stream:Stream stream = Stream.of("a");
  • 使用Stream.generate()创建无限Stream:Stream infiniteStream = Stream.generate(() -> 1);

2、中间操作:

  • filter(Predicate predicate): 过滤满足条件的元素。
  • map(Function mapper): 将元素按照指定映射关系转换为另一种类型。
  • distinct(): 去除重复元素。
  • sorted(): 对元素进行自然排序。
  • limit(long maxSize): 限制Stream的元素个数。
  • skip(long n): 跳过前n个元素。

3、终端操作:

  1. forEach(Consumer action): 对每个元素执行指定操作。
  2. collect(Collector collector): 将Stream中的元素收集到一个集合中。
  3. toArray(): 将Stream转换为数组。
  4. reduce(BinaryOperator accumulator): 将元素进行归约操作。
  5. min(Comparator comparator): 找到最小元素。
  6. max(Comparator comparator): 找到最大元素。
  7. count(): 计算Stream中的元素个数。
  8. anyMatch(Predicate predicate): 判断是否有元素满足条件。
  9. allMatch(Predicate predicate): 判断是否所有元素都满足条件。
  10. noneMatch(Predicate predicate): 判断是否没有元素满足条件。
  11. findFirst(): 找到第一个元素。
  12. findAny(): 找到任意一个元素。

示例代码:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StreamExample {
    public static void main(String[] args) {
        List list = Arrays.asList("apple", "banana", "orange", "apple", "grape");

        // 中间操作
        List filteredList = list.stream()
                .filter(fruit -> fruit.startsWith("a"))
                .distinct()
                .map(String::toUpperCase)
                .sorted()
                .collect(Collectors.toList());

        System.out.println(filteredList); // Output: [APPLE]

        // 终端操作
        long count = list.stream()
                .filter(fruit -> fruit.startsWith("a"))
                .count();

        System.out.println(count); // Output: 2
    }
}

你可能感兴趣的:(jdk,java)