ラムダ式の紹介とストリームAPI分析
1.ラムダ式
Baidu百科事典:
ラムダ式は無名関数です。ラムダ式は数学のλ計算に基づいて名前が付けられています。ラムダ計算に直接対応しています。無名関数、つまり関数名のない関数です。ラムダ式はクロージャを表すことができます。
ラムダ式は、Java 8によって導入された重要な機能の1つです(Java 8の新機能の紹介)。これにより、関数をメソッドパラメーターとして渡すことができます。これは関数型プログラミング指向のアイデアであり、コードをより簡潔にすることができます。ある程度。その本質は構文糖です。
传统方式创建线程
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("传统方式创建线程");
}
}).start();
使用lambda方式创建线程
new Thread(() -> System.out.println("lambda方式创建线程")).start();
Lanmbdaは非常に簡潔で理解しやすいように見えます。Lambdaは、タイプがRunableであると推測することもできます。これは、驚くべきことです。
ラムダ式の文法は、1)メソッド入力2)矢印関数3)メソッド本体の3つの部分に分かれています。
(parameters) -> expression
或
(parameters) ->{
statements; }
2.機能インターフェースの説明
コードを通してラムダを簡単に理解し、java8でRunableがラムダをサポートできることを見てみましょう。
Runableのソースコードをチェックして、@ FunctionalInterfaceアノテーションがインターフェースで定義されていることを確認してください
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
@FunctionalInterfaceアノテーションを確認してください。最も重要なのはアノテーションです。次のコードスニペットは、英語の意味を要約しています。
package java.lang;
import java.lang.annotation.*;
/**
1)该注解只能标记在"有且仅有一个抽象方法"的接口上。
2)JDK8接口中的静态方法和默认方法,都不算是抽象方法。
3)接口默认继承java.lang.Object,所以如果接口显示声明覆盖了Object中方法,那么也不算抽象方法。
4)该注解不是必须的,如果一个接口符合"函数式接口"定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错。
5)1.8及以后版本开始支持
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {
}
インターフェイスがラムダ式をサポートする方法がわかったので、関数型インターフェイスを自分で定義してみましょう。
public class LambdaDemo {
/**定义函数式接口*/
public interface ImLambdaInterface {
void print();
}
/**定义执行方法*/
void testLambda(ImLambdaInterface demo) {
demo.print();
}
public static void main(String[] args) {
LambdaDemo demo = new LambdaDemo();
demo.testLambda(() -> System.out.println("你好,我在测试函数式接口"));
}
}
3.jdk独自の機能インターフェイスの概要
3.1機能
注:Function <T、R>は、パラメーターTの受け渡しとパラメーターRの返送をサポートしています。
例:
//使用场景:按照属性进行list排序
list.sort(Comparator.comparingInt(a -> a.getAge()));
//**框架源码使用欣赏:Comparator的比较器就是传入Function进行处理
public static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor) {
return (Comparator<T> & Serializable)
(c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2));
}
3.2 BiConsumer
注:BiConsumer <T、U>は、戻り値なしで2つのパラメーターTとUをサポートします。
例:
//使用场景:经常使用的map遍历其实就是BiConsumer
map.forEach((k, v) -> {
System.out.println("我是key" + k + ",我是Value" + v);
});
//**框架源码使用欣赏:HashMap源码直接取出key和value就是使用了BiConsumer
default void forEach(BiConsumer<? super K, ? super V> action) {
Objects.requireNonNull(action);
for (Map.Entry<K, V> entry : entrySet()) {
//源代码略.......
action.accept(k, v);
}
}
3.3サプライヤー
説明:サプライヤーは、ジェネリックオブジェクトの返送をサポートしています。単純なサンプルコードを直接書く方が空っぽかもしれませんが、ThreadLocalソースコードを直接見ると理解しやすくなります。
例:
//使用场景:ThreadLocal可以直接使用Supplier
private static final ThreadLocal<String> threadLocal = ThreadLocal.withInitial(() -> "初始值");
//**框架源码使用欣赏:ThreadLocal源码
public static <S> ThreadLocal<S> withInitial(Supplier<? extends S> supplier) {
return new SuppliedThreadLocal<>(supplier);
}
3.4述語
説明:関数Tを渡し、要件を満たしているかどうかを返します。Predicateには、Streamでのさまざまな使用シナリオがあります。
例:
//使用场景:ArrayList过滤实体属性,可以使用自带的removeIf,这个就是断言
List<Person> list = Stream.of(Person.builder().name("Kobe").age(28).build(),
Person.builder().name("Jordon").age(36).build()).collect(Collectors.toList());
list.removeIf((t) -> t.getAge() > 34);
//**框架源码使用欣赏:ArrayList.removeIf()源码
default boolean removeIf(Predicate<? super E> filter) {
boolean removed = false;
final Iterator<E> each = iterator();
while (each.hasNext()) {
if (filter.test(each.next())) {
each.remove();
removed = true;
}
}
return removed;
}
4.ストリームの紹介
Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。
Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。
Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
Streamの操作は、中間操作と終了操作の2つのカテゴリに分類できます。中間操作は操作のみを記録します。終了操作のみが実際の計算(つまり、遅延評価)をトリガーします。これは、Streamが大規模な反復を行う場合でもあります。コレクション。効率の理由の1つ。中間操作は、ステートレス操作とステートフル操作に分けることができます。前者は、要素の処理が前の要素の影響を受けないことを意味し、後者は、すべての要素が取得された後にのみ操作を続行できることを意味します。終了操作は、短絡操作と非短絡操作に分けることができます。これはよく理解する必要があります。前者は、特定の要素が条件を満たすときに最終結果が得られることを意味し、後者は、すべての要素が最終結果を得るために処理されます。
======未完成、続き