1. 程式人生 > >Java 8中一些常用的全新的函式式介面

Java 8中一些常用的全新的函式式介面

函式式介面

什麼是函式式介面?

函式式介面,@FunctionalInterface,簡稱FI,簡單的說,FI就是指僅含有一個抽象方法的介面,以@Functionalnterface標註,注意⚠️,這裡的抽象方法指的是該介面自己特有的抽象方法,而不包含它從其上級繼承過來的抽象方法,例如:

@FunctionalInterface
Interface FI{
   abstract judge(int a);
   abstract equals();      
}

上面這個介面儘管含有兩個抽象方法,但是它仍然是一個FI,因為equals抽象方法是其從超類Object中繼承的(當然這裡的“介面繼承超類Object”的說法很有爭議,但是不妨礙咱們這裡拿來理解FI這個概念),若是對於函數借口還有什麼不明白的,個人推薦一個部落格:

http://lucida.me/blog/java-8-lambdas-insideout-language-features/這篇部落格對java8中的一些新特性講解的非常好!!

Java8中常用的全新的介面

Predicate介面
Predicate 介面只有一個引數,返回boolean型別。該介面包含多種預設方法來將Predicate組合成其他複雜的邏輯(比如:與,或,非):

程式碼如下:

Predicate<String> predicate = (s) -> s.length() > 0;

predicate.test("foo");              // true
predicate.negate().test("foo"); // false Predicate<Boolean> nonNull = Objects::nonNull; Predicate<Boolean> isNull = Objects::isNull; Predicate<String> isEmpty = String::isEmpty; Predicate<String> isNotEmpty = isEmpty.negate();

Function 介面
Function 介面有一個引數並且返回一個結果,並附帶了一些可以和其他函式組合的預設方法(compose, andThen):

程式碼如下:

Function<String, Integer> toInteger = Integer::valueOf;
Function<String, String> backToString = toInteger.andThen(String::valueOf);
backToString.apply("123");     // "123"

Supplier 介面
Supplier 介面返回一個任意範型的值,和Function介面不同的是該介面沒有任何引數

程式碼如下:

Supplier<Person> personSupplier = Person::new;
personSupplier.get();   // new Person

Consumer 介面
Consumer 介面表示執行在單個引數上的操作。

程式碼如下:

Consumer<Person> greeter = (p) -> System.out.println("Hello, " + p.firstName);
greeter.accept(new Person("Luke", "Skywalker"));

Comparator 介面
Comparator 是老Java中的經典介面, Java 8在此之上添加了多種預設方法:

程式碼如下:

Comparator<Person> comparator = (p1, p2) -> p1.firstName.compareTo(p2.firstName);


Person p1 = new Person("John", "Doe");
Person p2 = new Person("Alice", "Wonderland");

comparator.compare(p1, p2);             // > 0
comparator.reversed().compare(p1, p2);  // < 0

並行Streams
Stream有序列和並行兩種,序列Stream上的操作是在一個執行緒中依次完成,而並行Stream則是在多個執行緒上同時執行。

下面的例子展示了是如何通過並行Stream來提升效能:

首先我們建立一個沒有重複元素的大表:

程式碼如下:

int max = 1000000;
List<String> values = new ArrayList<>(max);
for (int i = 0; i < max; i++) {
    UUID uuid = UUID.randomUUID();
    values.add(uuid.toString());
}

然後我們計算一下排序這個Stream要耗時多久,
序列排序

程式碼如下:

long t0 = System.nanoTime();

long count = values.stream().sorted().count();
System.out.println(count);

long t1 = System.nanoTime();

long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
System.out.println(String.format("sequential sort took: %d ms", millis));

// 序列耗時: 899 ms
並行排序

程式碼如下:

long t0 = System.nanoTime();


long count = values.parallelStream().sorted().count();
System.out.println(count);

long t1 = System.nanoTime();

long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
System.out.println(String.format("parallel sort took: %d ms", millis));

// 並行排序耗時: 472 ms
上面兩個程式碼幾乎是一樣的,但是並行版的快了50%之多,唯一需要做的改動就是將stream()改為parallelStream()。