Java : Lambda
Lambda
この文書は2021年12月21日に記録されています.
JavaのEssentialsおよびAPIドキュメントおよびその他の参照を参照してください.
関数プログラミングとは何か分からない場合は、googlingまたはPP vs OOP vs FPを参照してください.
インタフェースやギネス世界記録なども理解する必要があります.
また、一等公民の関数としての内容を読んでから戻ることをお勧めします.
ランダを使うときの注意点を読むことをお勧めします.
Stream for loopforeach()に変更すべきでない3つの理由
構成
次の内容が含まれます.
緒論
1.0. Functionとは?
1.1. 機能インタフェースとは?
Lamda Expression
Functional Interface
3.1. Function/BiFunction/TriFunction(custom)
3.2. Supplier
3.3. Consumer/BiConsumer
3.4. Predicate
3.5. UnaryOperator
Practice
緒論
緒論は以下の内容から構成されている.
次に、実践を通じて複雑な問題を解決しましょう.
Functionとは?
関数とは?
任意の機能の一部を実現します.
関数のコンポーネントは次のとおりです.
機能インタフェースとは?
デフォルトではFunctional Interface
abstractメソッドが1つしかないインタフェースを表します.
Lamdaと同様に、コードが簡潔であるという利点があります.
メソッドリファレンスとは?
メソッドの参照は次のとおりです.
既存宣言のメソッドを指定する機能です.
FI+Lamdaより省略が多い.
メソッドリファレンスを使用するには、使用するメソッドのパラメータと戻りタイプを熟知する必要があります.
Lamda Expression
Lamda Expressionについて簡単かつ簡単に説明します.
構造は次のとおりです.(Integer x)->{
System.out.print(x);
}
(Integer x)->{
return x+3;
}
方法と全く同じですが、形が違います.
以下に、さらに理解すべき点を示します.
(Integer x)->{
System.out.print(x);
}
(Integer x)->{
return x+3;
}
x->System.out.print(x);
x->x+3;
Functional Interface
機能インタフェースが非常に多い.
しかし,いくつかの重要なインタフェース,あるいはそれらがルートであることにも気づいた.
機能インタフェースには、次のものがあります.
この場合、用語が長すぎるため、FI+Lamdaと表記される.
Function
パラメータTと戻り値R
@FunctionalInterface
public interface Function <T, R> {
R apply(T t);
}
FI+Lamda,で第1|tを入力
作ってみよう!
Function <Integer, Integer> process1=(Integer number)->{
return number+10;
};
Function <Integer, Integer> process2=(Integer number)->{
return number*5;
};
Function <Integer, Integer> process3=(Integer number)->{
return number/3;
}
省略しましょう.Function <Integer, Integer> process1=number->number+10;
Function <Integer, Integer> process2=number->number*5;
Function <Integer, Integer> process3=number->number/3;
使ってみよう!System.out.print(process1.apply(50)); // 60
System.out.print(process2.apply(50)); // 250
System.out.print(process3.apply(50)); // 16
BiFunction
パラメータT、Uおよび戻り値R
@FunctionalInterface
public interface BiFunctioanl<T, U, R> {
R apply(T t, U u);
}
制作后は省略してみます!BiFunction<Integer, Integer, Integer> process1=(number1, numeber2)=> number1+number2;
BiFunction<Integer, Integer, Integer> process2=(number1, numeber2)=> number1-number2;
BiFunction<Integer, Integer, Integer> process3=(number1, numeber2)=> number1*number2;
BiFunction<Integer, Integer, Integer> process4=(number1, numeber2)=>
(number2==0) number1 : number1/number2;
使ってみよう!System.out.print(process1.apply(10,10); // 20
System.out.print(process2.apply(10,10); // 0
System.out.print(process3.apply(10,10); // 100
System.out.print(process4.apply(10,0); // 10
TriFunction (custom)
パラメータT、U、Vおよび戻り値R
@FunctionalInterface
public interface TriFunction<T, U, V, R> {
R apply(T t, V v, R r);
}
制作后は省略してみます!TriFunction<Integer, Integer, Integer, Integer> process=(x,y,z)->x+y+z;
使ってみよう!System.out.println(process.apply(100,10,1));
Supplier
戻り値T
@FunctionalInterface
public interface Supplier<T> {
T get();
}
制作后は省略してみます!Supplier<Integer> process=()->10;
Supplier<String> process=()->"하이";
使ってみよう!System.out.print(process.get());
Consumer
パラメータT
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
制作后は省略してみます!Consumer<Integer> process=number->System.out.print(number);
使ってみよう!process.accept(10); // 10
process.accept(30); // 30
一体どうして.2021年12月21日現在、なぜ使われているのか分かりませんが、
使える状況が見つかれば、次しかないはずです.
publci class Main {
public static void main(String[] args) {
List<Integer datas=new ArrayList<>(Arrays.asList(10,20,30,40,50));
Consumer<Integer> process=data->System.out.print(data);
}
public static void process(List<Integer> datas, Consumer<Integer> consumer) {
for(Integer data : datas) {
consumer.accept(data);
}
}
}
BiConsumer
パラメータT,U
@FunctionalInterface
public interface BiConsumer<T, U> {
void accept(T t, U u);
default BiConsumer<T, U> andThen(BiConsumer<? super T, ? super U> after) {
Objects.requireNonNull(after);
return (l, r) -> {
accept(l, r);
after.accept(l, r);
};
}
}
制作后は省略してみます!BiConsumer<Integer, String> process=(name, age)->
System.out.printf("%s 이의 나이는 %d 입니다.%n",name,age);
やってみるprocess.accept("unchaptered", 30);
一体どうして.public class Main {
public static void main(String[] args){
List<String> datas=new ArrayList<>(Arrays.asList("김팔순","김덕해","홍영수"));
BiConsumer<Integer, String> process=(index,name)->
System.out.printf("%d 번 사용자의 이름은 %s 입니다.%n",index,name);
}
public static void process(List<String> datas, BiConsumer<Integer, String> process) {
for(int i=0; i<datas.size(); i++){
process.accept(i, list.get(i));
}
}
}
Predicate
パラメータTと戻り値boolean
public interface Predicate<T> {
boolean test(T t);
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
default Predicate<T> negate() {
return (t) -> !test(t);
}
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}
一体どうして.public class Main {
public static void main(String[] args) {
Predicate<Integer> isPositive=x->x>0;
List<Integer> list=new ArrayList<>(Arrays.asList(10, 3, -5, 4, -2 , 0));
System.out.println("기본 | "+list);
System.out.println();
System.out.println(filter(list,isPositive)); // 10, 4
System.out.println(filter(list,isPositive.negate())); // -5, -2, 0
System.out.println(filter(list,isPositive.or(x->x==0))); // 10, 4, 0
System.out.println(filter(list,isPositive.and(x->x%2==0))); // 10, 4
System.out.println(filter(list,isPositive.and(x->x%2==0 && x%3!=0))); // 10, 4
System.out.println(filter(list,isPositive.and(x->x%2==0).and(x->x%3!=0))); //10,4
}
public static <T> List<T> filter(List<T> list, Predicate<T> condition) {
ArrayList<T> output=new ArrayList<>();
for(T element : list) {
if(condition.test(element)) {
output.add(element);
}
}
output.trimToSize();
return output; // 오토 업캐스팅 이루어짐
}
}
UnaryOperator
このインタフェースはFunctionの概念を継承し、パラメータと戻り値が同じ場合、1つのタイプのパラメータのみが使用されます.
@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {
static <T> UnaryOperator<T> identity() {
return t -> t;
}
}
Comparator
@FunctionalInterface
public interface Comparator<T> {
int compare(T o1, T o2);
}
付録|Comparatorは比較用のインタフェースです.オブジェクトの比較に使用したり、単純な値の比較に使用したりできます.
public class User {
private int id;
private String name;
public User(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() { /* 생략 */ } }
public String getName() { /* 생략 */ }
@Override public int hashCode() { /* 생략*/ } }
@Override public boolean equals(Object obj) { /* 생략 */ }
@Override public String toString() {
return "User [id=" + id + ", name=" + name + "]";
}
}
使用状況と結果の表示public class UserTest {
static void main(String[] args) {
List<User> userList=new ArrayList<>(10);
userList.add(new User(3,"ceil"));
userList.add(new User(1,"bellian"));
userList.add(new User(5,"angelica"));
System.out.println(userList+"\n");
Comparator<User> idComparator=(u1, u2)->u1.getId() - u2.getId();
Collections.sort(userList,idComparator);
System.out.println(userList+"\n");
Comparator<User> nameComparator=(u1, u2)->u1.getName().compareTo(u2.getName());
Collections.sort(userList,nameComparator);
System.out.println(userList+"\n");
}
}
Method Reference
ラムダが匿名類より優れているところでは、簡潔さが最大の特徴です.
しかしjavaには、ramdaよりも関数オブジェクトを簡潔にする方法があります.それは方法参照です.(::演算子を使用)
Effective Java 6 | Lamda, Stream
次のような機能があります.
ClassName::staticMethodName
Function<String, Integer> strToint=Integer::parseInt;
int number=strToint.apply("403");
System.out.print(number); // 403
objectName::instanceMethodName
String textA="hello";
String textB="world";
Predicate<String> equalsStrToStr=textA::equals
boolean bools=equalsStrToStr.test("hello"); // true
boolean bools2=equalsStrToStr.test(textA); // true
boolean bools3=equalsStrToStr.test(textB); // false
拡張
FI+LamdaとLazy Evaluationの使用
Supplierを使用してパフォーマンス+Lazy Evaluationを向上させる理由
上の使用例を見ているだけでは理由が分からないと思います.
しかし、Supplierが演算を担当すると、物語は異なります.
パラメータに一般関数を渡すと、すぐに実行されます.
ただし、Supplierはget()で実行時間を決定することができる.
これらを利用できるのがLazy Evaluationの概念です.
Lazy Evaluation
[Avascript]遅延評価によるパフォーマンスの向上
@Functional Interfaceを使用して、特定の機能の実行時間を決定できます.
この部分を理解していない人がいたら、下をチェックしてください.hello() // 기존의 메서드 방식
hello.get() // Functional Interface 에서 추구하는 방식
一般的な方法では,実行時間を名前()の形式で決定することは困難である.
ただし、@Functional Interfaceでは、名前.実行関数()の形式では、パラメータ化と呼び出しの実行を分離する大きな利点があります.
これは厳密な評価とLazy評価を実現できる.
上記のリンクから入る言語はJavaScriptに基づいています.
Javaベースの説明を探しましたが、完全な効果を説明する文章を見つけるのは難しいです.上の文章はもっと簡潔で正確に追加されています.const arr = [0, 1, 2, 3, 4, 5]
const result = arr.map(num => num + 10).filter(num => num % 2).slice(0, 2)
console.log(result) // [11, 13]
// 지연평가를 하기 위해서는 지연평가 용 함수(Java 의 Functional Interface) 를 만들어야 한다.
const arr = [0, 1, 2, 3, 4, 5]
const result = _.take(2, L.filter(num => num % 2, L.map(num => num + 10, arr)));
console.log(result) // [11, 13]
この内容の詳細については、下記の記事を参考にしてください.
[JS]ES 6による関数式プログラミング-12 take
Reference
この問題について(Java : Lambda), 我々は、より多くの情報をここで見つけました
https://velog.io/@unchapterd/Java-Lambda
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
hello() // 기존의 메서드 방식
hello.get() // Functional Interface 에서 추구하는 방식
const arr = [0, 1, 2, 3, 4, 5]
const result = arr.map(num => num + 10).filter(num => num % 2).slice(0, 2)
console.log(result) // [11, 13]
// 지연평가를 하기 위해서는 지연평가 용 함수(Java 의 Functional Interface) 를 만들어야 한다.
const arr = [0, 1, 2, 3, 4, 5]
const result = _.take(2, L.filter(num => num % 2, L.map(num => num + 10, arr)));
console.log(result) // [11, 13]
Reference
この問題について(Java : Lambda), 我々は、より多くの情報をここで見つけました https://velog.io/@unchapterd/Java-Lambdaテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol