2015-07-08 6 views
6

Consideriamo una classe Parent che contiene solo un attributo Integer. Ho creato 6 oggetti di classe genitore e i valori di attributo sono 100, 20, 300, 400, 500, null.Gestione di un attributo null utilizzando java 8 stream e ordinamento utilizzando espressioni lambda

Ora ho aggiunto tutti gli oggetti a un elenco (il nome dell'elenco è l'elenco). Quindi voglio ottenere gli oggetti il ​​cui valore attributo è maggiore di 100. Ho usato Java 8 stream per questo scopo.

Predicate<Entity> predicate = e -> e.getParentId() < 100; 
result = list.stream().filter(predicate).collect(Collectors.toList()); 

Voglio anche ordinare l'elenco in ordine decrescente. Ho usato il seguente codice per questo scopo.

Comparator<Entity> comp = (d1,d2) -> d2.getId().compareTo(d1.getId()); 
list.sort(comp); 

In entrambi i casi ottengo uno NullPointerException.

Come gestirlo?

+1

possibile duplicato di [Come dovremmo gestire jdk8 stream per valori nulli] (http://stackoverflow.com/questions/17081063/how-should-we-manage-jdk8-stream-for-null-values) – alfasin

+2

I 'non chiaro ... è 'e' che è' null', o 'e.getParentId()'? Se 'e.getParentId()' è dichiarato come 'Integer' (il tipo in scatola), potrebbe essere nullo. Ma poi quando viene convertito in un 'int' per confrontarlo a 100, il risultato sarà un' NullPointerException' se è 'null'. – ajb

risposta

5

Provare pre-filtraggio per soli non nulli parentId valori:

result = list.stream().filter(e -> e.getParentId() != null).filter(predicate).collect(Collectors.toList()); 

[modifica] appena visto, che l'attributo (e.parentId) sembra quello di essere null. In tal caso, la seconda cosa, l'ordinamento, si interrompe. Stai ordinando l'elenco originale, non quello filtrato. Prova result.sort(comp), quindi dovresti evitare l'NPE.

+4

Questo dovrebbe funzionare. Puoi anche fare '.filter (Objects :: nonNull)' – alfasin

+0

Il problema è che l'oggetto non è nullo, ma l'attributo è nullo, se il mio contiene 100 attributi e ho creato un elenco di quegli oggetti, in cui molti attributi possono avere valore null in alcuni degli oggetti nell'elenco, come dovrei gestirlo. –

1

si può fare:

Predicate<Entity> predicate = e -> e.getParentId() < 100; 
Predicate<Entity> nonNull = e -> e != null; 
result = list.stream().filter(nonNull) 
         .filter(predicate) 
         .collect(Collectors.toList()); 

Naturalmente, si potrebbe combinare i predicati in una sola, ma ho introdotto un secondo per una migliore leggibilità. Inoltre, sei libero di modificare il predicato nonNull per controllare l'intera entità o solo l'attributo id (o anche entrambi). Gioca un po 'con quello. :)

4

si può fare tutto in una Stream Pipeline:

List<Entity> result = 
    list.stream() 
     .filter(e -> e.getParentId()!=null) // it's not clear if the null 
              // is the Entity object itself 
              // (in which case it should be e!=null) 
              // or just the ParentId member 
     .filter(predicate) 
     .sorted(comp) 
     .collect(Collectors.toList()); 

BTW, secondo il testo della tua domanda, il predicato originale dovrebbe essere:

Predicate<Entity> predicate = e -> e.getParentId() > 100; // not < 100 
+2

Non filtrerà questo elemento 'e.getParentId() == null' elementi? Sta parlando di "e' essere nullo. – Codebender

+2

@Codebender I potrebbe aver letto erroneamente la domanda, ma sembrava che OP abbia creato oggetti con ID padre di '100,20,300,400,500, null', quindi ho assunto il null riferito a ParentId. Potrei sbagliarmi. – Eran

+0

@Codebender che non è chiaro. Penso che stia parlando del genitore che è nullo, il che è possibile se è un 'numero intero'. – ajb

2

sfruttare la potenza del un metodo di riferimento per rendere il codice ancora più compatta:

List<Entity> result = 
      list.stream() 
        .filter(Objects::nonNull) 
        .filter(predicate) 
        .sorted(comp) 
        .collect(Collectors.toList()); 
13

Tutte le risposte qui ruotano attorno a "buttare via gli elementi cattivi, quelli che hanno un valore nullo getParentId()". Questa potrebbe essere la risposta, se sono davvero cattive. Ma c'è un'altra alternativa: Comparators.nullsFirst (o l'ultima). Ciò consente di confrontare le cose che trattano un valore nullo come minore (o maggiore di) di tutti i valori non nulli, quindi non devi gettare gli elementi con un genitore nullo lontano.

Comparator<Entity> cmp = nullsLast(comparing(Entity::getParentId)); 
List<Entity> list = list.stream().sorted(cmp).collect(toList()); 

Si può fare una cosa simile per il filtraggio; definire il predicato come:

Predicate<Entity> predicate = e -> e.getParentId() != null 
             && e.getParentId() < 100; 
5

Sembra che siete alla ricerca di qualcosa di simile a:

list.sort(Comparator.comparing(Entity::getParent, 
           Comparator.nullsLast(Integer::compareTo))); 

Tutti gli elementi con nulla genitore saranno messi alla fine e il resto saranno ordinati da un genitore.

+1

questa soluzione ha funzionato per me. Perché non voglio filtrare valori nulli. – omerhakanbilici