2017-05-10 17 views
5

Ich habe ein Programm, das Text für bestimmte Attribute analysiert. Die Grundstruktur des Codes ist das gleiche für alle Attribute es nur in einer Zeile variiert: webDataField.containsAttributeXYZ(); wie hier zu sehen:Prädikate in Java 8

for (int index = 0; index < fields.size(); index++) { 
    WebDataField webDataField = fields.get(index); 
    boolean expectedCondition = webDataField.containsAttributeXYZ(); // Varies at this line.. 

    Double score = evaluateBooleanCondition(actualCondition, expectedCondition); 

    WebDataFields fieldName = webDataField.getFieldName(); 
    ... 
} 

Statt den gleichen Code für jede Bedingung zu schreiben (& mich in Code zu wiederholen) Ich würde möchte den Hauptteil des Codes einmal schreiben und die Bedingung (die wahr oder falsch ergibt) an die Methode übergeben.

Ich bin neu zu Java Predicate aber wenn ich richtig verstehe, ist dies genau die Funktion von Prädikaten in Java.

Erzwingt dies, dass ich jede Bedingung in eine eigene Klasse schreibe und dann diese Klasse die Schnittstelle Predicate implementieren lasse?

Wenn ja, wird die Funktion (die zuvor in einer Klasse deklariert wird, die ähnliche Funktionen enthält) müssen wie etwas umgewandelt werden:

class ContainsAttributeXYZ implements Predicate<Boolean> 

Dies würde bewirken, dass der Code desorientiert werden und eine große auslösen Erhöhung der Anzahl der Klassen im Programm (da jede Funktion in eine Klasse umgewandelt werden muss)

Oder habe ich etwas falsch verstanden, wie Prädikate in Java funktionieren? Gibt es eine andere Möglichkeit, dies zu tun? Hier

Dank

+0

Ich bin mir nicht sicher, was Sie fragen. Ein 'Prädikat' muss nicht als Klasse deklariert werden. Zum Beispiel, 'Prädikat p = (String s) -> s.length()> 5;' wird tun. – bradimus

+4

Ein 'Prädikat ' macht nicht viel Sinn. Wahrscheinlich möchten Sie 'Prädikat '. –

+0

Wie kommt es, dass Sie das [lambda] -Tag hinzugefügt haben und doch scheinbar keine Ahnung haben, was sie sind? – 4castle

Antwort

5

ist ein beispielhaftes Verfahren, das eine Predicate als Argument:

void processFields(List<WebDataField> fields, Predicate<WebDataField> predicate) { 
    for (WebDataField webDataField : fields) { 
     boolean expectedCondition = predicate.test(webDataField); 
    } 
} 

und würden Sie es nennen, indem ein Verfahren Bezug geben, wie folgt aus:

processFields(fields, WebDataField::containsAttributeXYZ); 
processFields(fields, WebDataField::containsAttributeABC); 

Dabei sind containsAttributeXYZ und containsAttributeABC Methoden der WebDataField Klasse, die boolean zurückgeben. Oder Sie können ein Lambda Inline erstellen, ohne WebDataField zu ändern. Z.B. :

processFields(fields, w -> w.getFieldName().length() > 5); 

Sie brauchen nicht eine Klasse zu erstellen, die Predicate

1

Sie implementiert brauchen keine neue Klasse erstellen Predicate zu erstellen. Dies liegt daran, dass Java 8 eine Lambda-Syntax hinzugefügt hat, die Sie sich als Kurzform für anonyme innere Klassen vorstellen können, die eine Schnittstelle mit nur einer Methode implementieren. Hier ein Beispiel:

Predicate<Boolean> containsXYZ = b -> { 
    return !b; 
}; 

Dies entspricht:

Predicate<Boolean> containsXYZ = new Predicate<Boolean>() { 
    public boolean test(Boolean b) { 
     return !b; 
    } 
}; 

Wenn Ihr Prädikat gibt nur das Ergebnis eines einzigen Ausdruck, kann es zu verkürzen:

Predicate<Boolean> containsXYZ = b -> !b; 

Alternativ Eine Funktion kann eine Referenz zu einer Methode sein:

Predicate<Boolean> containsXYZ = MyClass::myMethod; // for static methods, or 
Predicate<Boolean> containsXYZ = this::myMethod; // for instance methods 

Dies ist ein einzeiliges Prädikat, das true zurückgibt, wenn die Eingabe false ist, und umgekehrt.Nun, für Ihren Anwendungsfall, könnte man so etwas wie dies wollen:

static void checkAttributes(Predicate<WebDataField> containsAttributeXYZ) { 
    for (WebDataField webDataField : fields) { 
     boolean expectedCondition = containsAttributeXYZ.test(webDataField); 
     Double score = evaluateBooleanCondition(actualCondition, expectedCondition); 
     WebDataFields fieldName = webDataField.getFieldName(); 

     ... 
    } 
} 

Für eine gründliche Erklärung, wie Lambda-Ausdrücke Arbeit, lesen Sie die Java Tutorial.

+1

Das ist eine ziemlich ausführliche Art zu schreiben "b ->! B". Das geschweifte Klammern und Return-Schlüsselwort sind nicht erforderlich. – VGR

+2

@VGR Einverstanden, aber ich dachte, dass es für jemanden aus einem Java-Hintergrund, der (anscheinend) niemals zuvor Lambdas gesehen hat (d. H. Das OP), für mich besser lesbar wäre. Auf diese Weise sieht es wie eine Methode aus. –