2017-05-10 52 views
5

我有一個程序可以分析某些屬性的文本。該代碼的基本結構是相同的所有屬性,它僅在一行變化:webDataField.containsAttributeXYZ();如下所示: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(); 
    ... 
} 

而不是寫相同的代碼爲每個條件(&重複自己的代碼)我想喜歡一次性編寫代碼的主體,並將條件(評估爲true或false)傳遞給方法。

我是Java Predicate的新手,但如果我理解正確,這正是Java中謂詞的功能。

這是否會迫使我在自己的類中編寫每個條件,然後讓該類實現Predicate接口?

如果是的話,(這是在包含類似功能的一類先前聲明)的功能將需要轉換的東西,如:

class ContainsAttributeXYZ implements Predicate<Boolean> 

這會導致代碼變得迷失方向,並引發大增加了程序中的班級數量(因爲每個功能都需要轉換成班級)

或者我誤解了Predicates在Java中的工作方式?有沒有另外一種方法呢?

感謝

+0

我不確定你在問什麼。 「Predicate」不需要聲明爲一個類。例如,'Predicate p =(String s) - > s.length()> 5;'會做。 – bradimus

+4

'Predicate '沒有多大意義。您可能需要'Predicate '。 –

+0

它是如何添加[lambda]標籤,但顯然不知道它們是什麼? – 4castle

回答

5

下面是一個例子方法,它接受Predicate作爲參數:

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

,你會通過傳遞方法的參考,像這樣稱呼它:

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

其中containsAttributeXYZcontainsAttributeABC是返回booleanWebDataField類的方法。或者,您可以在不修改WebDataField的情況下創建內聯lambda。例如。 :

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

你並不需要創建一個實現Predicate

1

你並不需要創建一個新的類來創建一個Predicate類。這是因爲Java 8添加了lambda語法,您可以認爲這是使用一種方法實現接口的匿名內部類的簡寫。下面是一個例子:

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

這相當於:

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

如果您的謂詞只是返回單個表達式的結果,它可以被簡化爲:

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

替代地,函數可以參考一個方法:

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

這是一個單行謂詞,如果輸入爲false,則返回true,反之亦然。現在,爲您的使用情況下,你可能會想是這樣的:

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

     ... 
    } 
} 

對於如何lambda表達式工作的一個徹底的解釋,閱讀Java Tutorial

+1

這是編寫'b - >!b'的一種非常冗長的方式。大括號和返回關鍵字不是必需的。 – VGR

+2

@VGR同意,但我認爲這對於Java背景的人(顯然)從來沒有見過lambdas(即OP)的人來說可能更易讀。這樣,它看起來有點像一種方法。 –