Ik was de Java 8-bron aan het verkennen en vond dit specifieke deel van de code erg verrassend:
//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;
}
Is Math::max
zoiets als een methodeaanwijzer?
Hoe wordt een normale static
methode geconverteerd naar IntBinaryOperator
?
Antwoord 1, autoriteit 100%
Meestal zou men de methode reduce
aanroepen met behulp van Math.max(int, int)
als volgt:
reduce(new IntBinaryOperator() {
int applyAsInt(int left, int right) {
return Math.max(left, right);
}
});
Dat vereist veel syntaxis om gewoon Math.max
aan te roepen. Dat is waar lambda-expressies in het spel komen. Sinds Java 8 is het toegestaan om hetzelfde te doen op een veel kortere manier:
reduce((int left, int right) -> Math.max(left, right));
Hoe werkt dit? De java-compiler “detecteert”, dat u een methode wilt implementeren die twee int
s accepteert en één int
retourneert. Dit komt overeen met de formele parameters van de enige echte methode van interface IntBinaryOperator
(de parameter van methode reduce
die je wilt aanroepen). Dus de compiler doet de rest voor je – hij gaat er gewoon van uit dat je IntBinaryOperator
wilt implementeren.
Maar aangezien Math.max(int, int)
zelf voldoet aan de formele vereisten van IntBinaryOperator
, kan het direct worden gebruikt. Omdat Java 7 geen syntaxis heeft waarmee een methode zelf als argument kan worden doorgegeven (u kunt alleen methoderesultaten doorgeven, maar nooit methodeverwijzingen), werd de syntaxis ::
in Java 8 geïntroduceerd om referentiemethoden:
reduce(Math::max);
Merk op dat dit tijdens runtime door de compiler wordt geïnterpreteerd, niet door de JVM! Hoewel het verschillende bytecodes produceert voor alle drie de codefragmenten, zijn ze semantisch gelijk, dus de laatste twee kunnen worden beschouwd als korte (en waarschijnlijk efficiëntere) versies van de IntBinaryOperator
-implementatie hierboven!
(Zie ook Vertaling van Lambda-expressies)
Antwoord 2, autoriteit 49%
::
heet Method Reference. Het is in feite een verwijzing naar een enkele methode. d.w.z. het verwijst naar een bestaande methode op naam.
Korte uitleg:
Hieronder ziet u een voorbeeld van een verwijzing naar een statische methode:
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
kan net als objectreferenties worden doorgegeven en indien nodig worden geactiveerd. In feite kan het net zo gemakkelijk worden gebruikt als een verwijzing naar “normale” methoden van objecten als static
methoden. Bijvoorbeeld:
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
hierboven is een functionele interface. Om ::
volledig te begrijpen, is het ook belangrijk om functionele interfaces te begrijpen. Duidelijk een functionele interfaceis een interface met slechts één abstracte methode.
Voorbeelden van functionele interfaces zijn onder meer Runnable
, Callable
en ActionListener
.
Function
hierboven is een functionele interface met slechts één methode: apply
. Er is één argument voor nodig en het levert een resultaat op.
De reden waarom ::
s geweldig zijn, is dat:
Methodeverwijzingen zijn expressies die dezelfde behandeling hebben als lambda-expressies (…), maar in plaats van een methode-body te geven, verwijzen ze naar een bestaande methode bij naam.
Bijvoorbeeld in plaats van het lambdalichaam te schrijven
Function<Double, Double> square = (Double x) -> x * x;
Je kunt het gewoon doen
Function<Double, Double> square = Hey::square;
Tijdens runtime gedragen deze twee square
-methoden zich exact hetzelfde als elkaar. De bytecode kan wel of niet hetzelfde zijn (hoewel in het bovenstaande geval dezelfde bytecode wordt gegenereerd; compileer het bovenstaande en controleer met javap -c
).
Het enige belangrijke criterium waaraan moet worden voldaan is: de methode die u opgeeft, moet een soortgelijke handtekening hebben als de methode van de functionele interface die u gebruikt als objectreferentie.
Het onderstaande is illegaal:
Supplier<Boolean> p = Hey::square; // illegal
square
verwacht een argument en retourneert een double
. De get
-methode in Leverancierretourneert een waarde maar accepteert geen argument. Dit resulteert dus in een fout.
Een methodeverwijzing verwijst naar de methode van een functionele interface.(Zoals gezegd kunnen functionele interfaces elk slechts één methode hebben).
Nog enkele voorbeelden: de methode accept
in Consumentneemt een invoer maar geeft niets terug.
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
Hierboven, getRandom
accepteert geen argument en retourneert een double
. Dus elke functionele interface die voldoet aan de criteria van: neem geen argument en retourneer double
kan worden gebruikt.
Nog een voorbeeld:
Set<String> set = new HashSet<>();
set.addAll(Arrays.asList("leo","bale","hanks"));
Predicate<String> pred = set::contains;
boolean exists = pred.test("leo");
In het geval van geparametriseerde typen:
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;
Methodereferenties kunnen verschillende stijlen hebben, maar in wezen betekenen ze allemaal hetzelfde en kunnen ze eenvoudig worden gevisualiseerd als lambda’s:
- Een statische methode (
ClassName::methName
) - Een instantiemethode van een bepaald object (
instanceRef::methName
) - Een supermethode van een bepaald object (
super::methName
) - Een instantiemethode van een willekeurig object van een bepaald type (
ClassName::methName
) - A Class Constructor Reference (
ClassName::new
) - Een array-constructorreferentie (
TypeName[]::new
)
Zie http: // cr. OpenJDK.JAVA.net/~BRIANGOETZ/LAMBDA/LAMBDA-STATE-FINAL.HTML .
Antwoord 3, Autoriteit 5%
Ja, dat is waar. De ::
Operator wordt gebruikt voor de methode referenties. Dus, men kan statisch methoden uit klassen extraheren door deze of methoden van objecten te gebruiken. Dezelfde operator kan zelfs voor constructeurs worden gebruikt. Alle hier genoemde gevallen zijn ondertekend in het onderstaande codemonster.
De officiële documentatie van Oracle is te vinden hier .
U kunt een beter overzicht hebben van de JDK 8-wijzigingen in dit -artikel. In de -methode / constructeur referenties sectie is ook een codevoorbeeld verstrekt:
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);
}
}
Antwoord 4, Autoriteit 3%
Het lijkt het weinig laat, maar hier zijn mijn twee cent. A Lambda-expressie wordt gebruikt om anonieme methoden te maken. Het doet niets anders dan een bestaande methode, maar het is duidelijker om door de naam rechtstreeks naar de methode te verwijzen. En Methode Referentie stelt ons in staat om dat te doen met behulp van methode-referentie-operator ::
.
Overweeg de volgende eenvoudige klasse waarbij elke medewerker een naam en cijfer heeft.
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;
}
}
Stel dat we een lijst met werknemers hebben die zijn geretourneerd door een methode en we willen de werknemers sorteren op hun cijfer. We weten dat we gebruik kunnen maken van anonieme klasse als:
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());
}
});
waarbij getDummyEmployee() een methode is als:
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")
);
}
Nu weten we dat Comparatoreen functionele interface. Een functionele interfaceis degene met precies één abstracte methode (hoewel deze een of meer standaard- of statische methoden kan bevatten). Lambda-expressie biedt implementatie van @FunctionalInterface
, zodat een functionele interface slechts één abstracte methode kan hebben. We kunnen lambda-expressie gebruiken als:
employeeList.sort((e1,e2) -> e1.getGrade().compareTo(e2.getGrade())); // lambda exp
Het lijkt allemaal goed, maar wat als de klasse Employee
ook een vergelijkbare methode biedt:
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);
}
}
In dit geval is het duidelijker om de naam van de methode zelf te gebruiken. Daarom kunnen we rechtstreeks naar methode verwijzen door methodeverwijzing te gebruiken als:
employeeList.sort(Employee::compareByGrade); // method reference
Volgens docszijn er vier soorten methodeverwijzingen :
+----+-------------------------------------------------------+--------------------------------------+
| | 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 |
+------------------------------------------------------------+--------------------------------------+
Antwoord 5, autoriteit 3%
::
is een nieuwe operator in Java 8 die wordt gebruikt om naar een methode van een bestaande klasse te verwijzen. Je kunt verwijzen naar statische methoden en niet-statische methoden van een klasse.
Voor het verwijzen naar statische methoden is de syntaxis:
ClassName :: methodName
Voor het verwijzen naar niet-statische methoden is de syntaxis
objRef :: methodName
En
ClassName :: methodName
De enige voorwaarde voor het verwijzen van een methode is dat die methode bestaat in een functionele interface, die compatibel moet zijn met de methodeverwijzing.
Methodeverwijzingen creëren, wanneer geëvalueerd, een instantie van de functionele interface.
Gevonden op: http://www.spokecs.com/2014/ 08/method-references-in-java-8.html
Antwoord 6, autoriteit 2%
Dit is een methodeverwijzing in Java 8. De Oracle-documentatie is hier .
Zoals vermeld in de documentatie…
De methodereferentie Person::compareByAge is een verwijzing naar een statische
methode.Het volgende is een voorbeeld van een verwijzing naar een instantiemethode van a
bepaald object:
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);
De methodeverwijzing myComparisonProvider::compareByName roept de methode CompareByName op
dat is onderdeel van het object myComparisonProvider. De JRE leidt daaruit af dat de
methode type argumenten, in dit geval (Persoon, Persoon).
Antwoord 7
:: Operatoris geïntroduceerd in Java 8 voor methodereferenties. Een methodeverwijzing is de verkorte syntaxis voor een lambda-expressie die slechts EEN methode uitvoert. Hier is de algemene syntaxis van een methodeverwijzing:
Object :: methodName
We weten dat we lambda-expressieskunnen gebruiken in plaats van een anonieme klas gebruiken. Maar soms is de lambda-expressie eigenlijk gewoon een aanroep van een methode, bijvoorbeeld:
Consumer<String> c = s -> System.out.println(s);
Om de code duidelijker te maken, kun je die lambda-expressie omzetten in een methodereferentie:
Consumer<String> c = System.out::println;
Antwoord 8
De :: staat bekend als methodereferenties. Laten we zeggen dat we een methode berekenPrice van de klasse Aankoop willen aanroepen. Dan kunnen we het schrijven als:
Purchase::calculatePrice
Het kan ook worden gezien als een korte vorm van het schrijven van de lambda-expressie, omdat methodeverwijzingen worden omgezet in lambda-expressies.
Antwoord 9
Ik vond deze bronerg interessant.
In feite is het de Lambdadie verandert in een Dubbele dubbele punt.
De dubbele dubbele punt is beter leesbaar.
We volgen die stappen:
STAP1:
// We create a comparator of two persons
Comparator c = (Person p1, Person p2) -> p1.getAge().compareTo(p2.getAge());
STAP2:
// We use the interference
Comparator c = (p1, p2) -> p1.getAge().compareTo(p2.getAge());
STAP3:
// The magic using method reference
Comparator c = Comparator.comparing(Person::getAge);
Antwoord 10
Dus Ik zie hier talloze antwoorden die eerlijk gezegd te ingewikkeld zijn, en dat is een understatement.
Het antwoord is vrij eenvoudig: :: het heet een Method Referenceshttps://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html
Dus ik zal niet kopiëren en plakken, op de link kun je alle informatie vinden als je naar de tabel scrolt.
Laten we nu even kijken naar wat een methodereferentie is:
A::benigszinsvervangt de volgende inline lambda-expressie: (params …) -> A.b(params …)
Om dit te correleren met uw vragen, is het noodzakelijk om een Java lambda-expressie te begrijpen. Wat niet moeilijk is.
Een inline lambda-expressie is vergelijkbaar met een gedefinieerdefunctionele interface (een interface die niet meer en niet minder dan 1 methode heeft).
Laten we even kijken wat ik bedoel:
InterfaceX f = (x) -> x*x;
InterfaceX moet een functionele interface zijn. Elke functionele interface, het enige wat belangrijk is aan InterfaceX voor die compiler is dat je het formaat definieert:
InterfaceX kan dit allemaal zijn:
interface InterfaceX
{
public Integer callMe(Integer x);
}
of dit
interface InterfaceX
{
public Double callMe(Integer x);
}
of algemener:
interface InterfaceX<T,U>
{
public T callMe(U x);
}
Laten we de eerste casus nemen en de inline lambda-expressie die we eerder hebben gedefinieerd.
Vóór Java 8 had je het op dezelfde manier kunnen definiëren:
InterfaceX o = new InterfaceX(){
public int callMe (int x)
{
return x*x;
} };
Functioneel gezien is het hetzelfde. Het verschil zit hem meer in hoe de compiler dit waarneemt.
Nu we de inline lambda-expressie hebben bekeken, gaan we terug naar Method References (::). Laten we zeggen dat je een klas als deze hebt:
class Q {
public static int anyFunction(int x)
{
return x+5;
}
}
Aangezien de methode Anyfunctions dezelfde typen heeft als Interfacx CallMe , kunnen we die twee equivaleren met een methode-referentie.
We kunnen het als volgt schrijven:
InterfaceX o = Q::anyFunction;
en dat is overeen met dit:
InterfaceX o = (x) -> Q.anyFunction(x);
Een cool ding en voordeel van methode-referenties zijn dat in eerste instantie totdat u ze aan variabelen toewijst, typeert u typisch. U kunt ze dus passeren als parameters voor een equivalent uitziende (heeft dezelfde gedefinieerde typen) functionele interface. Wat precies is wat er in uw zaak gebeurt
Antwoord 11
return reduce(Math::max);
is niet gelijk op return reduce(max());
Maar het betekent, zoiets als volgt:
IntBinaryOperator myLambda = (a, b)->{(a >= b) ? a : b};//56 keystrokes I had to type -_-
return reduce(myLambda);
U kunt slechts 47 toetsaanslagen beslaan Als u dit als deze schrijft
return reduce(Math::max);//Only 9 keystrokes ^_^
Antwoord 12
Aangezien veel antwoorden hier het gedrag van ::
goed hebben uitgelegd, zou ik bovendien willen verduidelijken dat de ::
operator niet exact dezelfde handtekening hoeft te hebben als de verwijzende Functionele interface als deze bijvoorbeeld wordt gebruikt voor variabelen. Laten we aannemen dat we een BinaryOperatornodig hebben die het type TestObjectheeft. Op de traditionele manier wordt het als volgt geïmplementeerd:
BinaryOperator<TestObject> binary = new BinaryOperator<TestObject>() {
@Override
public TestObject apply(TestObject t, TestObject u) {
return t;
}
};
Zoals je ziet in anonieme implementatie vereist het twee TestObject-argumenten en retourneert het ook een TestObject-object. Om aan deze voorwaarde te voldoen door de operator ::
te gebruiken, kunnen we beginnen met een statische methode:
public class TestObject {
public static final TestObject testStatic(TestObject t, TestObject t2){
return t;
}
}
en bel dan:
BinaryOperator<TestObject> binary = TestObject::testStatic;
Ok, het is goed gecompileerd. Hoe zit het als we een instantiemethode nodig hebben? Laten we TestObject updaten met de instantiemethode:
public class TestObject {
public final TestObject testInstance(TestObject t, TestObject t2){
return t;
}
public static final TestObject testStatic(TestObject t, TestObject t2){
return t;
}
}
Nu hebben we toegang tot exemplaar zoals hieronder:
TestObject testObject = new TestObject();
BinaryOperator<TestObject> binary = testObject::testInstance;
Deze code compileert prima, maar onder één niet:
BinaryOperator<TestObject> binary = TestObject::testInstance;
Mijn Eclipse vertel me “kan geen statische verwijzing doen naar de niet-statische methode-testinstantie (TestObject, TestObject) van het type TestObject …”
Eerlijk genoeg is het een instantie-methode, maar als we overbelasten testInstance
zoals hieronder:
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;
}
}
en bel:
BinaryOperator<TestObject> binary = TestObject::testInstance;
De code compileert gewoon prima. Omdat het testInstance
met één parameter zal bellen in plaats van dubbele. Oké, wat gebeurde er met onze twee parameter? Laat afdrukken en zie:
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;
}
}
Wat zal het volgende opleveren:
1418481495
303563356
Test instance called. this.hashCode:1418481495
Given parameter hashCode:303563356
Ok, dus JVM is slim genoeg om param1.testInstance(param2) aan te roepen. Kunnen we testInstance
van een andere bron gebruiken, maar niet TestObject, d.w.z.:
public class TestUtil {
public final TestObject testInstance(TestObject t){
return t;
}
}
En bel:
BinaryOperator<TestObject> binary = TestUtil::testInstance;
Het compileert gewoon niet en de compiler zegt: “Het type TestUtil definieert testInstance(TestObject, TestObject) niet”. De compiler zoekt dus naar een statische referentie als deze niet van hetzelfde type is. Oké, hoe zit het met polymorfisme? Als we de laatste modifiers verwijderen en onze klasse SubTestObjecttoevoegen:
public class SubTestObject extends TestObject {
public final TestObject testInstance(TestObject t){
return t;
}
}
En bel:
BinaryOperator<TestObject> binary = SubTestObject::testInstance;
Het compileert niet zo goed, de compiler zoekt nog steeds naar statische referentie. Maar onderstaande code zal prima compileren omdat het een test doorstaat:
public class TestObject {
public SubTestObject testInstance(Object t){
return (SubTestObject) t;
}
}
BinaryOperator<TestObject> binary = TestObject::testInstance;
*Ik ben net aan het studeren, dus ik ben erachter gekomen door te proberen en te zien, corrigeer me gerust als ik het mis heb
Antwoord 13
In java-8 is Streams Reducer in eenvoudige werken een functie die twee waarden als invoer neemt en na enige berekening het resultaat oplevert. dit resultaat wordt in de volgende iteratie ingevoerd.
in het geval van de functie Math:max, blijft de methode het maximum van twee doorgegeven waarden retourneren en uiteindelijk heb je het grootste aantal in de hand.
Antwoord 14
In oudere Java-versies kunt u in plaats van “::” of lambd het volgende gebruiken:
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();
}
Of doorgeven aan de methode:
public static void doSomething(Action action) {
action.execute();
}
Antwoord 15
De dubbele dubbele punt (::) operator, in Java ook wel methode-referentie-operator genoemd, wordt gebruikt om een methode aan te roepen door ernaar te verwijzen met behulp van zijn klasse. Ze gedragen zich precies zoals de lambda-uitdrukkingen. Het enige verschil met lambda-expressies is dat dit een directe verwijzing naar de methode op naam gebruikt in plaats van een gemachtigde voor de methode te geven.
Syntaxis:
<Class name>::<method name>
Dit symbool kan worden gebruikt in plaats van Lamda-uitdrukkingen
Programma:
// Java code to print the elements of Stream
// without using double colon operator
import java.util.stream.*;
class MyClass {
public static void main(String[] args)
{
// Get the stream
Stream<String> stream
= Stream.of("Testing","Program");
// Print the stream
stream.forEach(s -> System.out.println(s));
}
}
Uitvoer:
Testing
Program
De regel stream.forEach(s -> System.out.println(s));
kan worden vervangen door
stream.forEach(System.out::println);
Ook de eerste methode wordt meestal gebruikt tijdens het programmeren.
Antwoord 16
Tijdens runtime gedragen ze zich exact hetzelfde. De bytecode kan wel/niet hetzelfde zijn (Voor bovenstaande Incase genereert het dezelfde bytecode (vul hierboven in en controleer javaap -c;))
Tijdens runtime gedragen ze zich exact hetzelfde.methode(math::max);,het genereert dezelfde wiskunde (vul hierboven in en controleer javap -c;))
Antwoord 17
De vorige antwoorden zijn vrij compleet met betrekking tot wat ::
Method-referentie doet. Om samen te vatten, biedt het een manier om te verwijzen naar een methode (of constructor) zonder het uit te voeren, en wanneer geëvalueerd, maakt het een exemplaar van de functionele interface die de context Target Type biedt.
Hieronder staan twee voorbeelden om een object te vinden met de maximale waarde in een ArrayList
met en zonder het gebruik van ::
methode-referentie. Verklaringen zijn in de onderstaande opmerkingen.
Zonder het gebruik van ::
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());
}
}
Met het gebruik van ::
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);
}
}
Antwoord 18
Double Colon I.E. ::
Operator wordt geïntroduceerd in Java 8 als een methode-referentie . Methode Referentie is een vorm van Lambda-expressie die wordt gebruikt om de bestaande methode door de naam te verwijzen.
ClassName :: MethodName
ex: –
stream.forEach(element -> System.out.println(element))
Met behulp van Double Colon ::
stream.forEach(System.out::println(element))