::(ダブルコロン)Java 8の演算子


956

私はJava 8を探索していましたソースを調査していて、コードのこの特定の部分が非常に驚くべきであることに気付きました。

//defined in IntPipeline.java
@Override
public final OptionalInt reduce(IntBinaryOperator op) {
    return evaluate(ReduceOps.makeInt(op));
}

@Override
public final OptionalInt max() {
    return reduce(Math::max); //this is the gotcha line
}

//defined in Math.java
public static int max(int a, int b) {
    return (a >= b) ? a : b;
}

あるMath::maxメソッドポインタのようなもの?通常のstaticメソッドはどのように変換されIntBinaryOperatorますか?


60
コンパイラーが提供する関数に基づいてインターフェースの実装を自動生成するのは構文上の砂糖です(ラムダ全体を既存のコードベースで使いやすくするため)。
2013年

4
java.dzone.com/articles/java-lambda-expressions-vsは役立つかもしれませんが、トピックの深いところを見ていませんでした
Pontus Backlund

8
@ニートは、何を言っているのかわからない限り、厳密には「構文上の砂糖」ではありません。つまり、「xはyの構文糖」です。
2013年

6
@Ingoは、使用するたびにラムダの新しいオブジェクトを作成します。TestingLambda$$Lambda$2/8460669そしてTestingLambda$$Lambda$3/110432532回の呼び出しで作成されました。
Narendra Pathai 2013年

13
ラムダとメソッド参照は、「プレーンな古い匿名の内部クラス」ではありません。programmers.stackexchange.com/a/181743/59134を参照してください。はい、必要に応じて、新しいクラスとインスタンスが必要に応じてオンザフライで作成されますが、必要な場合のみです。
スチュアートマークス

回答:


1022

通常、次のようにしてreduceメソッドを呼び出しMath.max(int, int)ます。

reduce(new IntBinaryOperator() {
    int applyAsInt(int left, int right) {
        return Math.max(left, right);
    }
});

を呼び出すだけでは、多くの構文が必要になりますMath.max。そこでラムダ式が登場します。Java 8以降では、同じことをはるかに短い方法で実行できます。

reduce((int left, int right) -> Math.max(left, right));

これはどのように作動しますか?2つintのを受け入れて1つを返すメソッドを実装することをJavaコンパイラが「検出」しますint。これは、インターフェースの唯一のメソッドのIntBinaryOperatorパラメーター(reduce呼び出したいメソッドのパラメーター)に相当します。したがって、コンパイラが残りの作業を行います-実装することを前提としていますIntBinaryOperator

ただし、Math.max(int, int)それ自体がの正式な要件を満たしてIntBinaryOperatorいるため、直接使用できます。Java 7には、メソッド自体を引数として渡すことができる構文がないため(メソッドの結果のみを渡すことができ::ますが、メソッド参照はできません)、構文はJava 8でメソッドを参照するために導入されました。

reduce(Math::max);

これは、実行時にJVMではなくコンパイラによって解釈されることに注意してください!3つのコードスニペットすべてに対して異なるバイトコードを生成しますが、それらは意味的に等しいため、最後の2つはIntBinaryOperator上記の実装の短い(そしておそらくより効率的な)バージョンと見なすことができます!

ラムダ式の翻訳も参照)


489

::メソッドリファレンスと呼ばれます。これは基本的に単一のメソッドへの参照です。つまり、既存のメソッドを名前で参照します。

簡単な説明
以下は、静的メソッドへの参照の例です。

class Hey {
     public static double square(double num){
        return Math.pow(num, 2);
    }
}

Function<Double, Double> square = Hey::square;
double ans = square.apply(23d);

squareオブジェクト参照と同じように渡して、必要なときにトリガーできます。実際、オブジェクトの「通常の」メソッドへの参照と同じくらい簡単に使用できますstatic。例えば:

class Hey {
    public double square(double num) {
        return Math.pow(num, 2);
    }
}

Hey hey = new Hey();
Function<Double, Double> square = hey::square;
double ans = square.apply(23d);

Function上記は機能的なインターフェースです。を完全に理解するには::、機能的なインターフェイスも理解することが重要です。明らかに、機能的なインターフェースは、1つの抽象メソッドのみをです。

機能インタフェースの例にはRunnableCallable、およびActionListener

Function上記は、メソッドが1つしかない機能的なインターフェースですapply。1つの引数を取り、結果を生成します。


::sがすばらしい理由は次のとおりです

メソッド参照は、ラムダ式(...)と同じ処理を行う式ですが、メソッド本体を提供する代わりに、既存のメソッドを名前で参照します。

例えばラムダ本体を書く代わりに

Function<Double, Double> square = (Double x) -> x * x;

簡単にできます

Function<Double, Double> square = Hey::square;

実行時に、これら2つのsquareメソッドは互いにまったく同じように動作します。バイトコードは同じ場合も同じでない場合もあります(ただし、上記の場合、同じバイトコードが生成されます。上記をコンパイルして、javap -c)。

満たす唯一の主要な基準は、次のとおりです。提供するメソッドには、オブジェクト参照として使用する機能インターフェイスのメソッドと同様のシグネチャが必要です。

以下は違法です:

Supplier<Boolean> p = Hey::square; // illegal

square引数を期待し、を返しますdoubleサプライヤーgetメソッドは値を返しますが、引数を取りません。したがって、これはエラーになります。

メソッド参照は、機能インターフェースのメソッドを指します。(前述のように、機能インターフェースはそれぞれ1つのメソッドしか持てません)。

さらにいくつかの例:Consumeracceptメソッドは入力を受け取りますが、何も返しません。

Consumer<Integer> b1 = System::exit;   // void exit(int status)
Consumer<String[]> b2 = Arrays::sort;  // void sort(Object[] a)
Consumer<String> b3 = MyProgram::main; // void main(String... args)

class Hey {
    public double getRandom() {
        return Math.random();
    }
}

Callable<Double> call = hey::getRandom;
Supplier<Double> call2 = hey::getRandom;
DoubleSupplier sup = hey::getRandom;
// Supplier is functional interface that takes no argument and gives a result

上記でgetRandomは、引数を取らず、を返しますdouble。したがって、次の基準を満たす関数型インターフェース:引数を取らずに返すdouble使用することができます。

もう一つの例:

Set<String> set = new HashSet<>();
set.addAll(Arrays.asList("leo","bale","hanks"));
Predicate<String> pred = set::contains;
boolean exists = pred.test("leo");

パラメータ化されたタイプの場合

class Param<T> {
    T elem;
    public T get() {
        return elem;
    }

    public void set(T elem) {
        this.elem = elem;
    }

    public static <E> E returnSame(E elem) {
        return elem;
    }
}

Supplier<Param<Integer>> obj = Param<Integer>::new;
Param<Integer> param = obj.get();
Consumer<Integer> c = param::set;
Supplier<Integer> s = param::get;

Function<String, String> func = Param::<String>returnSame;

メソッド参照は異なるスタイルを持つことができますが、基本的にそれらはすべて同じ意味であり、単純にラムダとして視覚化できます。

  1. 静的メソッド(ClassName::methName
  2. 特定のオブジェクトのインスタンスメソッド(instanceRef::methName
  3. 特定のオブジェクトのスーパーメソッド(super::methName
  4. 特定のタイプの任意のオブジェクトのインスタンスメソッド(ClassName::methName
  5. クラスコンストラクターリファレンス(ClassName::new
  6. 配列コンストラクター参照(TypeName[]::new

詳細については、http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.htmlを参照してください


6
ご説明ありがとうございます。要約すると、「::」を使用して、FunctionalInterface(lambda)を満たすメソッドを抽出します:ClassX :: staticMethodX、またはinstanceX :: instanceMethodX "
jessarah

55

はい、それは本当だ。::オペレータは、この方法の参照のために使用されます。したがって、クラスから静的メソッドを抽出したり、オブジェクトからメソッドを抽出したりできます。コンストラクターでも同じ演算子を使用できます。ここで説明するすべてのケースは、以下のコードサンプルに例示されています。

オラクルの公式ドキュメントはここにあります

この記事では、JDK 8の変更の概要を詳しく説明しています。メソッド/コンストラクタ参照セクションのコード例も提供されます。

interface ConstructorReference {
    T constructor();
}

interface  MethodReference {
   void anotherMethod(String input);
}

public class ConstructorClass {
    String value;

   public ConstructorClass() {
       value = "default";
   }

   public static void method(String input) {
      System.out.println(input);
   }

   public void nextMethod(String input) {
       // operations
   }

   public static void main(String... args) {
       // constructor reference
       ConstructorReference reference = ConstructorClass::new;
       ConstructorClass cc = reference.constructor();

       // static method reference
       MethodReference mr = cc::method;

       // object method reference
       MethodReference mr2 = cc::nextMethod;

       System.out.println(cc.value);
   }
}

良い説明はここで見つけるものです:doanduyhai.wordpress.com/2012/07/14/...
Olimpiu POP

1
@RichardTingle method(Math::max);は呼び出しであり、メソッドの定義は次のようになりpublic static void method(IntBinaryOperator op){System.out.println(op.applyAsInt(1, 2));}ます。それがその使い方です。
Narendra Pathai 2013年

2
C#に慣れている人にとっては、DelegateType d = new DelegateType(MethodName);と同様です。
Adrian Zanescu 2013年

27

少し遅いようですが、ここは私の2セントです。ラムダ式は、匿名メソッドを作成するために使用されます。既存のメソッドを呼び出すだけですが、名前で直接メソッドを参照する方が明確です。また、メソッド参照により、メソッド参照演算子を使用してそれを行うことができます::

次の単純なクラスで、各従業員に名前と学年があるとします。

public class Employee {
    private String name;
    private String grade;

    public Employee(String name, String grade) {
        this.name = name;
        this.grade = grade;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGrade() {
        return grade;
    }

    public void setGrade(String grade) {
        this.grade = grade;
    }
}

なんらかの方法で返された従業員のリストがあり、その従業員をグレードでソートしたいとします。匿名クラスを次のように使用できることがわかっています。

    List<Employee> employeeList = getDummyEmployees();

    // Using anonymous class
    employeeList.sort(new Comparator<Employee>() {
           @Override
           public int compare(Employee e1, Employee e2) {
               return e1.getGrade().compareTo(e2.getGrade());
           }
    });

ここで、getDummyEmployee()は次のようなメソッドです。

private static List<Employee> getDummyEmployees() {
        return Arrays.asList(new Employee("Carrie", "C"),
                new Employee("Fanishwar", "F"),
                new Employee("Brian", "B"),
                new Employee("Donald", "D"),
                new Employee("Adam", "A"),
                new Employee("Evan", "E")
                );
    }

これで、コンパレータは機能的なインターフェースであることがわかりました。機能インタフェースは、正確に1つの抽象メソッド(それは1つ以上のデフォルトまたは静的メソッドが含まれていてもよいが)を有するものです。ラムダ式は実装を提供する@FunctionalInterfaceので、関数型インターフェースは1つの抽象メソッドしか持つことができません。ラムダ式は次のように使用できます。

employeeList.sort((e1,e2) -> e1.getGrade().compareTo(e2.getGrade())); // lambda exp

それはすべて良いようですが、クラスEmployeeが同様のメソッドも提供している場合はどうなりますか?

public class Employee {
    private String name;
    private String grade;
    // getter and setter
    public static int compareByGrade(Employee e1, Employee e2) {
        return e1.grade.compareTo(e2.grade);
    }
}

この場合、メソッド名自体を使用するとより明確になります。したがって、次のようにメソッド参照を使用して、メソッドを直接参照できます。

employeeList.sort(Employee::compareByGrade); // method reference

あたりとしてドキュメントメソッドリファレンスの4種類があります。

+----+-------------------------------------------------------+--------------------------------------+
|    | Kind                                                  | Example                              |
+----+-------------------------------------------------------+--------------------------------------+
| 1  | Reference to a static method                          | ContainingClass::staticMethodName    |
+----+-------------------------------------------------------+--------------------------------------+
| 2  |Reference to an instance method of a particular object | containingObject::instanceMethodName | 
+----+-------------------------------------------------------+--------------------------------------+
| 3  | Reference to an instance method of an arbitrary object| ContainingType::methodName           |
|    | of a particular type                                  |                                      |  
+----+-------------------------------------------------------+--------------------------------------+
| 4  |Reference to a constructor                             | ClassName::new                       |
+------------------------------------------------------------+--------------------------------------+

25

::既存のクラスのメソッドを参照するために使用されるJava 8に含まれる新しい演算子です。クラスの静的メソッドと非静的メソッドを参照できます。

静的メソッドを参照する場合、構文は次のとおりです。

ClassName :: methodName 

非静的メソッドを参照する場合、構文は次のとおりです。

objRef :: methodName

そして

ClassName :: methodName

メソッドを参照するための唯一の前提条件は、メソッドが機能参照に存在することです。これは、メソッド参照と互換性がある必要があります。

メソッド参照は、評価されると、機能インターフェースのインスタンスを作成します。

上の場所:http : //www.speakingcs.com/2014/08/method-references-in-java-8.html


22

これはJava 8のメソッドリファレンスです。Oracleのドキュメントはこちらですです。

ドキュメントに記載されているように...

メソッド参照Person :: compareByAgeは、静的メソッドへの参照です。

以下は、特定のオブジェクトのインスタンスメソッドへの参照の例です。

class ComparisonProvider {
    public int compareByName(Person a, Person b) {
        return a.getName().compareTo(b.getName());
    }

    public int compareByAge(Person a, Person b) {
        return a.getBirthday().compareTo(b.getBirthday());
    }
}

ComparisonProvider myComparisonProvider = new ComparisonProvider();
Arrays.sort(rosterAsArray, myComparisonProvider::compareByName); 

メソッド参照myComparisonProvider :: compareByNameは、オブジェクトmyComparisonProviderの一部であるcompareByNameメソッドを呼び出します。JREはメソッドタイプ引数(この場合は(Person、Person))を推測します。


2
ただし、「compareByAge」メソッドは静的ではありません。
abbas 2016年

3
@abbasもcompareByNameではありません。したがって、オブジェクトを使用して参照演算子を通じてこれらの非静的メソッドにアクセスします。静的な場合は、ComparisionProvider :: someStaticMethod
Seshadri R

6

::演算子は、メソッド参照のためにJava 8で導入されました。メソッド参照は、1つのメソッドのみを実行するラムダ式の省略構文です。メソッドリファレンスの一般的な構文は次のとおりです。

Object :: methodName

匿名クラスを使用する代わりにラムダ式を使用できることがわかっています。しかし、時々、ラムダ式は実際にはいくつかのメソッドの呼び出しにすぎません。たとえば、

Consumer<String> c = s -> System.out.println(s);

コードをより明確にするために、そのラムダ式をメソッド参照に変換できます。

Consumer<String> c = System.out::println;

3

::はメソッド参照として知られています。PurchaseクラスのcalculatePriceメソッドを呼び出したいとしましょう。次に、次のように記述します。

Purchase::calculatePrice

メソッド参照はラムダ式に変換されるため、ラムダ式を記述する短い形式と見なすこともできます。


ネストされたメソッド参照を作成できますか?例:groupingBy(Order :: customer :: name)

そのようにネストされたメソッド参照を作成することはできません
Kirby

3

私が見つかりました。このソースは非常に興味深いです。

実際、ダブルコロンに変わるのはラムダです。ダブルコロンの方が読みやすくなっています。次の手順に従います。

ステップ1:

// We create a comparator of two persons
Comparator c = (Person p1, Person p2) -> p1.getAge().compareTo(p2.getAge());

ステップ2:

// We use the interference
Comparator c = (p1, p2) -> p1.getAge().compareTo(p2.getAge());

STEP3:

// The magic using method reference
Comparator c = Comparator.comparing(Person::getAge);

3
のように思わPerson::getAge()れるPerson::getAge
Qwertiy 2017

2

return reduce(Math::max);ある等しくないreturn reduce(max());

しかし、それはこのようなものを意味します:

IntBinaryOperator myLambda = (a, b)->{(a >= b) ? a : b};//56 keystrokes I had to type -_-
return reduce(myLambda);

このように書くと、47回のキーストロークを保存できます

return reduce(Math::max);//Only 9 keystrokes ^_^

2

ここでの多くの回答は::動作をよく説明しているので:: 、インスタンス変数に使用する場合演算子は参照する機能インターフェースとまったく同じシグネチャを持つ必要がないことを明確にしたいと思いますTestObject型のBinaryOperatorが必要だとしましょ。従来の方法では、次のように実装されています。

BinaryOperator<TestObject> binary = new BinaryOperator<TestObject>() {

        @Override
        public TestObject apply(TestObject t, TestObject u) {

            return t;
        }
    };

匿名実装でわかるように、2つのTestObject引数が必要で、TestObjectオブジェクトも返されます。::演算子を使用してこの条件を満たすには、静的メソッドから始めることができます。

public class TestObject {


    public static final TestObject testStatic(TestObject t, TestObject t2){
        return t;
    }
}

次に呼び出す:

BinaryOperator<TestObject> binary = TestObject::testStatic;

うまくコンパイルされました。インスタンスメソッドが必要な場合はどうでしょうか。インスタンスメソッドでTestObjectを更新しましょう:

public class TestObject {

    public final TestObject testInstance(TestObject t, TestObject t2){
        return t;
    }

    public static final TestObject testStatic(TestObject t, TestObject t2){
        return t;
    }
}

これで、次のようにインスタンスにアクセスできます。

TestObject testObject = new TestObject();
BinaryOperator<TestObject> binary = testObject::testInstance;

このコードは正常にコンパイルされますが、以下のコードではコンパイルできません。

BinaryOperator<TestObject> binary = TestObject::testInstance;

私の日食は「タイプTestObjectから非静的メソッドtestInstance(TestObject、TestObject)への静的参照を作成できません...」

十分に公平なインスタンスメソッドですが、testInstance以下のようにオーバーロードすると:

public class TestObject {

    public final TestObject testInstance(TestObject t){
        return t;
    }

    public final TestObject testInstance(TestObject t, TestObject t2){
        return t;
    }

    public static final TestObject testStatic(TestObject t, TestObject t2){
        return t;
    }
}

そして呼び出す:

BinaryOperator<TestObject> binary = TestObject::testInstance;

コードは正常にコンパイルされます。それはtestInstance二重の代わりに単一のパラメーターで呼び出すからです。では、2つのパラメータはどうなりましたか?印刷して見てみましょう:

public class TestObject {

    public TestObject() {
        System.out.println(this.hashCode());
    }

    public final TestObject testInstance(TestObject t){
        System.out.println("Test instance called. this.hashCode:" 
    + this.hashCode());
        System.out.println("Given parameter hashCode:" + t.hashCode());
        return t;
    }

    public final TestObject testInstance(TestObject t, TestObject t2){
        return t;
    }

    public static final TestObject testStatic(TestObject t, TestObject t2){
        return t;
    }
}

どちらが出力されます:

 1418481495  
 303563356  
 Test instance called. this.hashCode:1418481495
 Given parameter hashCode:303563356

JVMはparam1.testInstance(param2)を呼び出すのに十分スマートです。testInstanceTestObjectではなく、別のリソースから使用できますか?

public class TestUtil {

    public final TestObject testInstance(TestObject t){
        return t;
    }
}

そして呼び出す:

BinaryOperator<TestObject> binary = TestUtil::testInstance;

それはコンパイルせず、コンパイラーは「タイプTestUtilはtestInstance(TestObject、TestObject)を定義しません」と通知します。そのため、コンパイラは、同じ型でない場合に静的参照を探します。多態性についてはどうですか?最終修飾子を削除してSubTestObjectクラスを追加すると、次のようになります。

public class SubTestObject extends TestObject {

    public final TestObject testInstance(TestObject t){
        return t;
    }

}

そして呼び出す:

BinaryOperator<TestObject> binary = SubTestObject::testInstance;

コンパイルも行われず、コンパイラは静的参照を探します。しかし、以下のコードはis-aテストに合格しているため、正常にコンパイルされます。

public class TestObject {

    public SubTestObject testInstance(Object t){
        return (SubTestObject) t;
    }

}

BinaryOperator<TestObject> binary = TestObject::testInstance;

*ただ勉強しているだけなので、試してみてわかりました。間違っていた場合は、遠慮なく修正してください。


2

java-8では、Streams Reducerは単純な作業で2つの値を入力として取り、いくつかの計算後に結果を返す関数です。この結果は次の反復で提供されます。

Math:max関数の場合、メソッドは渡された2つの値の最大値を返し続け、最終的に最大の数を手にします。


1

実行時、それらはまったく同じように動作します。バイトコードは同じである場合とそうでない場合があります(上記のIncaseの場合、同じバイトコードが生成されます(上記に従ってコンパイルし、javaap -c;を確認してください))。

実行時にそれらはまったく同じように動作します。method(math :: max);、同じ数学を生成します(上記のようにコンパイルし、javap -c;を確認してください)。


1

古いJavaバージョンでは、「::」やlambdの代わりに、次を使用できます。

public interface Action {
    void execute();
}

public class ActionImpl implements Action {

    @Override
    public void execute() {
        System.out.println("execute with ActionImpl");
    }

}

public static void main(String[] args) {
    Action action = new Action() {
        @Override
        public void execute() {
            System.out.println("execute with anonymous class");
        }
    };
    action.execute();

    //or

    Action actionImpl = new ActionImpl();
    actionImpl.execute();
}

またはメソッドに渡します:

public static void doSomething(Action action) {
    action.execute();
}

1

だから私は率直に言って複雑過ぎるたくさんの答えをここに見ます、そしてそれは控えめな表現です。

答えは非常に簡単です:::メソッド参照と呼ばれ ますhttps://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html

そのため、リンクにコピーアンドペーストしないでください。テーブルまでスクロールすると、すべての情報を見つけることができます。


ここで、メソッド参照とは何かを簡単に見てみましょう。

A :: B は、次のインラインラムダ式をいくらか置き換えます:(params ...)-> AB(params ...)

これを質問と関連付けるには、Javaラムダ式を理解する必要があります。難しいことではありません。

インラインラムダ式は、定義された 機能インターフェイス(1つ以上のメソッドを持つインターフェイス)に似ています。私が意味することを簡単に見てみましょう:

InterfaceX f = (x) -> x*x; 

InterfaceXは機能的なインターフェイスでなければなりません。機能的なインターフェイスであれば、そのコンパイラにとってInterfaceXで重要なことは、形式を定義することだけです。

InterfaceXは次のいずれかです。

interface InterfaceX
{
    public Integer callMe(Integer x);
}

またはこれ

interface InterfaceX
{
    public Double callMe(Integer x);
}

またはより一般的:

interface InterfaceX<T,U>
{
    public T callMe(U x);
}

最初に提示されたケースと、前に定義したインラインラムダ式を見てみましょう。

Java 8以前は、次のように定義することもできました。

 InterfaceX o = new InterfaceX(){
                     public int callMe (int x, int y) 
                       {
                        return x*x;
                       } };

機能的には同じです。違いは、コンパイラがこれをどのように認識するかです。

インラインラムダ式を確認したので、メソッド参照(::)に戻りましょう。次のようなクラスがあるとします。

class Q {
        public static int anyFunction(int x)
             {
                 return x+5;
             } 
        }

メソッドanyFunctionsはInterfaceX callMeと同じタイプなので、これら2つをメソッドリファレンスで同等化できます。

次のように書くことができます:

InterfaceX o =  Q::anyFunction; 

これはこれと同等です:

InterfaceX o = (x) -> Q.anyFunction(x);

メソッド参照の優れた点と利点は、最初は変数に割り当てるまでは型がないことです。そのため、それらをパラメーターとして、同等の(同じ型が定義されている)機能のインターフェイスに渡すことができます。それはあなたのケースで正確に何が起こるかです


1

以前の答えは何に関してかなり完全です ::メソッド参照がです。要約すると、メソッド(またはコンストラクタ)を実行せずに参照する方法を提供し、評価されると、ターゲットタイプのコンテキストを提供する機能インターフェイスのインスタンスを作成します。

以下はArrayList::メソッド参照を使用してWITHおよびWITHOUT で最大値を持つオブジェクトを見つける2つの例です。説明は以下のコメントにあります。


使用せずに ::

import java.util.*;

class MyClass {
    private int val;
    MyClass (int v) { val = v; }
    int getVal() { return val; }
}

class ByVal implements Comparator<MyClass> {
    // no need to create this class when using method reference
    public int compare(MyClass source, MyClass ref) {
        return source.getVal() - ref.getVal();
    }
}

public class FindMaxInCol {
    public static void main(String args[]) {
        ArrayList<MyClass> myClassList = new ArrayList<MyClass>();
        myClassList.add(new MyClass(1));
        myClassList.add(new MyClass(0));
        myClassList.add(new MyClass(3));
        myClassList.add(new MyClass(6));

        MyClass maxValObj = Collections.max(myClassList, new ByVal());
    }
}

の使用で ::

import java.util.*;

class MyClass {
    private int val;
    MyClass (int v) { val = v; }
    int getVal() { return val; }
}

public class FindMaxInCol {
    static int compareMyClass(MyClass source, MyClass ref) {
        // This static method is compatible with the compare() method defined by Comparator. 
        // So there's no need to explicitly implement and create an instance of Comparator like the first example.
        return source.getVal() - ref.getVal();
    }

    public static void main(String args[]) {
        ArrayList<MyClass> myClassList = new ArrayList<MyClass>();
        myClassList.add(new MyClass(1));
        myClassList.add(new MyClass(0));
        myClassList.add(new MyClass(3));
        myClassList.add(new MyClass(6));

        MyClass maxValObj = Collections.max(myClassList, FindMaxInCol::compareMyClass);
    }
}

-1

二重コロンie ::演算子は、メソッド参照としてJava 8で導入されました。メソッド参照は、既存のメソッドを名前で参照するために使用されるラムダ式の形式です。

classname :: methodName

例:-

  • stream.forEach(element -> System.out.println(element))

ダブルコロンを使用する ::

  • stream.forEach(System.out::println(element))
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.