2015-09-01 6 views
8

Ho il seguente codice:Java 8 - Come utilizzare il predicato che ha una funzione con parametro?

public boolean isImageSrcExists(String imageSrc) { 
    int resultsNum = 0; 
    List<WebElement> blogImagesList = driver.findElements(blogImageLocator); 

    for (WebElement thisImage : blogImagesList) { 
     if (thisImage.getAttribute("style").contains(imageSrc)) { 
      resultsNum++; 
     } 
    } 

    if (resultsNum == 2) { 
     return true; 
    } else { 
     return false; 
    } 
} 

Qual è il modo corretto di convertire in modo da utilizzare Java 8 Stream s?

Quando si tenta di utilizzare map(), viene visualizzato un messaggio di errore dal getAttribute non è un Function.

int a = (int) blogImagesList.stream() 
          .map(WebElement::getAttribute("style")) 
          .filter(s -> s.contains(imageSrc)) 
          .count(); 
+1

potremmo fare qualche thingy "curry", ma non è probabilmente vale la pena - 'curry (:: getAttribute, "style") ' – ZhongYu

risposta

10

Non è possibile fare esattamente ciò che si desidera: i parametri espliciti non sono consentiti nei riferimenti del metodo.

ma si potrebbe ...

... creare un metodo che restituisce un valore booleano e harcoded la chiamata a getAttribute("style"):

public boolean getAttribute(final T t) { 
    return t.getAttribute("style"); 
} 

Ciò consentirebbe di utilizzare il metodo ref:

int a = (int) blogImagesList.stream() 
       .map(this::getAttribute) 
       .filter(s -> s.contains(imageSrc)) 
       .count(); 

... o si potrebbe definire una variabile per contenere la funzione:

final Function<T, R> mapper = t -> t.getAttribute("style"); 

Ciò permette di passare semplicemente la variabile

int a = (int) blogImagesList.stream() 
       .map(mapper) 
       .filter(s -> s.contains(imageSrc)) 
       .count(); 

... o si potrebbe curry e combinare i due approcci di cui sopra (questo è certamente orribilmente eccessivo)

public Function<T,R> toAttributeExtractor(String attrName) { 
    return t -> t.getAttribute(attrName); 
} 

Poi si farebbe bisogno di chiamare toAttributeExtractor per ottenere un Function e passare che nel map:

final Function<T, R> mapper = toAttributeExtractor("style"); 
int a = (int) blogImagesList.stream() 
       .map(mapper) 
       .filter(s -> s.contains(imageSrc)) 
       .count(); 

Anche se, realisticamente, semplicemente utilizzando un lambda sarebbe più facile (come si fa sulla riga successiva):

int a = (int) blogImagesList.stream() 
       .map(t -> t.getAttribute("style")) 
       .filter(s -> s.contains(imageSrc)) 
       .count(); 
+1

Perché hai tutte queste soluzioni imbarazzanti nel mezzo invece di andare direttamente alla soluzione alla fine? –

+1

@LouisWasserman perché l'OP voleva una soluzione alternativa: volevo illustrare che la soluzione semplice che l'OP stava già utilizzando è la migliore. –

5

Non è possibile passare un parametro a un riferimento di metodo. È possibile utilizzare invece un'espressione lambda:

int a = (int) blogImagesList.stream() 
          .map(w -> w.getAttribute("style")) 
          .filter(s -> s.contains(imageSrc)) 
          .count(); 
+3

Mi sono permesso di formattare il codice in modo da poterlo leggere senza scorrere. –

+1

@PeterLawrey Grazie :) – Eran

Problemi correlati