Javaを学んでいる非Javaプログラマーとして、私は現在Supplier
、Consumer
インターフェースとインターフェースについて読んでいます。そして、私は彼らの用法と意味に頭を抱えることはできません。いつ、なぜこれらのインターフェースを使用するのですか?誰かが私にこれの簡単な素人の例を教えてもらえますか?私の理解するのに十分ではないDocの例を見つけています。
Javaを学んでいる非Javaプログラマーとして、私は現在Supplier
、Consumer
インターフェースとインターフェースについて読んでいます。そして、私は彼らの用法と意味に頭を抱えることはできません。いつ、なぜこれらのインターフェースを使用するのですか?誰かが私にこれの簡単な素人の例を教えてもらえますか?私の理解するのに十分ではないDocの例を見つけています。
回答:
これはサプライヤーです:
public Integer getInteger() {
return new Random().nextInt();
}
これは消費者です:
public void sum(Integer a, Integer b) {
System.out.println(a + b);
}
つまり、素人の言葉で言えば、サプライヤーは(戻り値のように)ある値を返すメソッドです。一方、コンシューマは(メソッド引数のように)いくつかの値を消費し、それらに対していくつかの操作を行うメソッドです。
それらは次のようなものに変わります:
// new operator itself is a supplier, of the reference to the newly created object
Supplier<List<String>> listSupplier = ArrayList::new;
Consumer<String> printConsumer = a1 -> System.out.println(a1);
BiConsumer<Integer, Integer> sumConsumer = (a1, a2) -> System.out.println(a1 + a2);
使い方については、非常に基本的な例は次のようになります:Stream#forEach(Consumer)
メソッド。これは、反復するストリームから要素を消費するコンシューマーを受け取り、それぞれに対して何らかのアクションを実行します。おそらくそれらを印刷します。
Consumer<String> stringConsumer = (s) -> System.out.println(s.length());
Arrays.asList("ab", "abc", "a", "abcd").stream().forEach(stringConsumer);
のような機能的なインターフェースの意味を理解するのが難しい理由java.util.function
は、ここで定義されたインターフェースには意味がないためです。それらは、意味論ではなく、主に構造を表すために存在します。
これは、ほとんどのJava APIで非定型です。クラスやインターフェースなどの典型的なJava APIには意味があり、それが表すもののメンタルモデルを開発し、それを使用してその操作を理解することができます。java.util.List
たとえば考えてみてください。A List
は他のオブジェクトのコンテナです。シーケンスとインデックスがあります。リストに含まれるオブジェクトの数は、によって返されsize()
ます。各オブジェクトには、0..size-1(両端を含む)の範囲のインデックスがあります。インデックスiのオブジェクトは、次の呼び出しによって取得できますlist.get(i)
。など。
の機能インターフェイスにjava.util.function
は、そのような意味はありません。代わりに、それらは、引数の数、戻り値の数、および(場合によっては)引数または戻り値がプリミティブかどうかなど、関数の構造を単に表すインターフェースです。したがってFunction<T,R>
、T型の単一の引数を取り、R型の値を返す関数を表すようなものがあります。それでおしまい。その機能は何をしますか?まあ、1つの引数を取り、1つの値を返す限り、何でもできます。それがの仕様Function<T,R>
が「1つの引数を受け入れて結果を生成する関数を表す」に過ぎない理由です。
明らかに、私たちがコードを書いているとき、それには意味があり、その意味はどこかから来ている必要があります。機能的なインターフェースの場合、意味はそれらが使用されるコンテキストに由来します。インターフェースFunction<T,R>
は単独では意味がありません。ただし、java.util.Map<K,V>
APIには次のものがあります。
V computeIfAbsent(K key, Function<K,V> mappingFunction)
(簡潔にするために省略されたワイルドカード)
ああ、この使用はFunction
「マッピング機能」です。それは何をしますか?このコンテキストkey
で、がまだマップに存在しない場合、マッピング関数が呼び出され、キーが渡され、値を生成することが期待され、結果のキーと値のペアがマップに挿入されます。
したがって、仕様Function
(またはその他の機能的インターフェース)を見て、それらの意味を理解することはできません。それらが他のAPIでどこで使用されているかを見て、それらの意味を理解する必要があります。その意味はそのコンテキストにのみ適用されます。
A Supplier
は、引数を取らず、値を返す任意のメソッドです。その仕事は文字通り、期待されるクラスのインスタンスを提供することです。たとえば、「getter」メソッドへのすべての参照はSupplier
public Integer getCount(){
return this.count;
}
そのインスタンスメソッド参照myClass::getCount
はのインスタンスですSupplier<Integer>
。
A Consumer
は引数を取り、何も返さないメソッドです。副作用のために呼び出されます。Java用語では、a Consumer
はvoid
メソッドのイディオムです。'setter'メソッドは良い例です:
public void setCount(int count){
this.count = count;
}
そのインスタンスメソッド参照myClass::setCount
は、Consumer<Integer>
およびのインスタンスですIntConsumer
。
A Function<A,B>
は、ある型の引数を取り、別の型を返す任意のメソッドです。これは「変換」と呼ぶことができます。はをFunction<A,B>
取り、A
を返しますB
。注目すべきは、指定された値に対してA
、関数が常に特定の値を返す必要があることですB
。A
そしてB
実際には、次のような同じタイプであることができます。
public Integer addTwo(int i){
return i+2;
}
そのインスタンスメソッド参照myClass:addTwo
はa Function<Integer, Integer>
およびToIntFunction<Integer>
です。
getterへのClassメソッド参照は、関数のもう1つの例です。
public Integer getCount(){
return this.count;
}
そのクラスメソッド参照MyClass::getCount
はFunction<MyClass,Integer>
およびのインスタンスですToIntFunction<MyClass>
。
なぜコンシューマー/サプライヤー/その他の機能インターフェースがjava.util.functionパッケージで定義されているのか:コンシューマーとサプライヤーは、Java 8で提供される組み込み機能インターフェースの2つです。これらすべての組み込み機能インターフェースの目的は、共通の関数記述子(関数メソッドのシグネチャ/定義)を持つ関数インターフェイスの準備が整った「テンプレート」を提供します。
我々は我々が合格した場合、別のタイプR.に型Tに変換するために必要としていたとしましょう任意の方法は、その官能/抽象メソッドのパラメータをとる機能インタフェースを定義する必要があること、次に、メソッドのパラメータとして、次のように定義された関数をタイプTの入力として、タイプRのパラメーターを出力として提供します。今、このような多くのシナリオがあり、プログラマーは最終的に彼らのニーズのために複数の機能的なインターフェースを定義することになります。この種のシナリオを回避し、プログラミングを容易にし、機能インターフェースの使用に共通の標準をもたらすために、述語、関数、コンシューマー、サプライヤーなどの組み込みの機能インターフェースのセットが定義されています。
コンシューマーは何をしますか:コンシューマー機能インターフェイスは入力を受け入れ、その入力で何かを行い、出力を提供しません。その定義は次のようになります(Javaソースから)-
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
ここで、accept()は、入力を受け取り、出力を返さないfunction \ abstractメソッドです。そのため、Integerを入力する場合は、出力なしでそれを使って何かを実行してから、独自のインターフェースを定義する代わりに、Consumerのインスタンスを使用します。
サプライヤーは何をしますか:サプライヤー機能インターフェースは入力を取りませんが、出力を返します。このように定義されています(Javaソースから)-
@FunctionalInterface
public interface Supplier<T> {
T get();
}
Integerなど、何かを返すが、出力を取得しない関数が必要な場合は、Supplierのインスタンスを使用します。
コンシューマーとサプライヤーのインターフェイスの使用例とともに、より明確にする必要がある場合は、同じブログ記事を参照できます-http://www.javabrahman.com/java-8/java-8-java-util- function-consumer-tutorial-with-examples / および http://www.javabrahman.com/java-8/java-8-java-util-function-supplier-tutorial-with-examples/
私の質問に対する私の答えを参照してくださいここでは、さらに別の、ここではなく、短期では、これらの新しいインタフェースが提供大会と記述性ファンキーな方法+(使用に皆のためにこのような連鎖します.forEach(someMethod().andThen(otherMethod()))
消費者:何かを取り、何かをし、何も返さない:void accept(T t)
サプライヤー: 何もせず、何かを返します:( T get()
消費者の逆、基本的には普遍的な「ゲッター」方法)
// Consumer: It takes something (a String) and does something (prints it)
List<Person> personList = getPersons();
personList.stream()
.map(Person::getName)
.forEach(System.out::println);
サプライヤー:コードの実行タイミングなど、反復的なコードをラップする
public class SupplierExample {
public static void main(String[] args) {
// Imagine a class Calculate with some methods
Double result1 = timeMe(Calculate::doHeavyComputation);
Double result2 = timeMe(Calculate::doMoreComputation);
}
private static Double timeMe(Supplier<Double> code) {
Instant start = Instant.now();
// Supplier method .get() just invokes whatever it is passed
Double result = code.get();
Instant end = Instant.now();
Duration elapsed = Duration.between(start,end);
System.out.println("Computation took:" + elapsed.toMillis());
return result;
}
}
Laymen用語では、
サプライヤーはデータを提供しますが、データを消費しません。プログラミング用語では、引数をとらずに値を返すメソッド。新しい値を生成するために使用されます。
http://codedestine.com/java-8-supplier-interface/
コンシューマはデータを消費しますが、データを返しません。プログラミング用語では、複数の引数を取り、値を返さないメソッド。
コンシューマとサプライヤは、Javaによって提供されるインターフェースです。コンシューマはリスト要素の反復に使用され、サプライヤは供給オブジェクトの反復に使用されます
コードのデモで簡単に理解できます。
消費者
package com.java.java8;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
/**
* The Class ConsumerDemo.
*
* @author Ankit Sood Apr 20, 2017
*/
public class ConsumerDemo {
/**
* The main method.
*
* @param args
* the arguments
*/
public static void main(String[] args) {
List<String> str = new ArrayList<>();
str.add("DEMO");
str.add("DEMO2");
str.add("DEMO3");
/* Consumer is use for iterate over the List */
Consumer<String> consumer = new Consumer<String>() {
@Override
public void accept(String t) {
/* Print list element on consile */
System.out.println(t);
}
};
str.forEach(consumer);
}
}
サプライヤー
package com.java.java8;
import java.util.function.Supplier;
/**
* The Class SupplierDemo.
*
* @author Ankit Sood Apr 20, 2017
*/
public class SupplierDemo {
/**
* The main method.
*
* @param args
* the arguments
*/
public static void main(String[] args) {
getValue(() -> "Output1");
getValue(() -> "OutPut2");
}
/**
* Gets the value.
*
* @param supplier
* the supplier
* @return the value
*/
public static void getValue(Supplier<?> supplier) {
System.out.println(supplier.get());
}
}
最も簡単な答えは次のとおりです。
コンシューマーはFunction <T、Void>と見なすことができます。サプライヤは、Function <Void、T>として表示できます。
Consumer
とSupplier
あなたも検索することがチュートリアルのためにConsumer
...