2016-06-06 9 views
-1

Die einfachste Form der Frage ist, ich habe eine Sammlung und ich möchte alle Elemente, die ihre value == null. Ich möchte nicht an Ort und Stelle löschen (Ich möchte eine neue Karte erhalten, damit meine ursprüngliche Karte sicher ist).java - Wie entfernt man alle Nullelemente von einer Map?

Ich füge mehr Elemente zu ADDITIONAL_QUERY abhängig davon, welche API ich später anrufe.

Weitere Details: Ich habe gerade meine Retrofit lib auf Version 2.0 aktualisiert. Ich habe @FieldMap Map<String, String> additionalQuery in den meisten meiner APIs (ca. 100 APIs). Laut ihrer Dokumentation betrachten FieldMap, "Named Schlüssel/Wert-Paare für eine formularbasierte Anfrage. Ein Null-Wert für die Karte, als Schlüssel oder als Wert ist nicht erlaubt.", Wie in Java Doc erwähnt (Es ist so lustig dass ihr Doc im Web sagt, Sie können https://square.github.io/retrofit/2.x/retrofit/index.html?retrofit2/http/class-use/FieldMap.html).

Da APIs sehr oft aufgerufen werden, suche ich nach einem Weg mit geringen Overhead und schnell natürlich. Jede Idee wäre dankbar, danke.

+2

Iterate über der Eintrag gesetzt und zu einer neuen Karte hinzugefügt? Fehle ich etwas? – shmosel

Antwort

0

Wenn Sie Guava haben, können Sie eine gefilterte Ansicht erstellen Kopieren auf eine neue Karte zu vermeiden:

Map<String, String> filtered = Maps.filterValues(ADDITIONAL_QUERY, new Predicate<String>() { 
    @Override 
    public boolean apply(String value) { 
     return value != null; 
    } 
}); 

Da Sie auf Java 8, Sie verkürzen kann das Prädikat wie folgt aus:

Map<String, String> filtered = Maps.filterValues(ADDITIONAL_QUERY, Objects::nonNull); 
+0

In Java 8 ist hier auch ein Lambda anwendbar ('value -> value! = Null'). – bcsb1001

+2

@ bcsb1001 oder 'Objekte :: nonNull'. Aber das ist eine Android-Frage, also sind Lambdas out. – shmosel

+0

Lambda braucht mehr Speicherplatz, um es zu vermeiden. – Hesam

4

können Sie verwenden:

map.values().removeAll(Collections.singleton(null)); 
+3

OP sagte ausdrücklich, er möchte sie nicht an Ort und Stelle löschen. – shmosel

+0

@smosel dann kopieren Sie einfach die Karte zuerst – njzk2

+0

@ njzk2, warum kopieren Sie die gesamte Karte nur um die Nullwerte zu entfernen, vor allem, wenn OP versucht, Overhead zu vermeiden? – shmosel

0

Sie können diese verwenden:

Map newMap = (HashMap) ADDITIONAL_QUERY.clone();; 

newMap.values().remove(null); 
+0

Sie kopieren nur die Referenz, nicht die Karte. – shmosel

+0

@smossel Korrigiert –

0

Eine mögliche Lösung ist die folgende:

public <K, V> Map<K,V> removeNulls(Map<K,V> original) { 
    return original.entrySet().stream().filter(e -> e.getValue() != null) 
       .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue())); 
} 

Wenn die Karte sehr groß ist, dann könnten Sie auch parallelStream() anstelle von stream()

+0

Sie können alternativ 'Objects :: nonNull',' Entry :: getKey' und 'Entry :: getValue' verwenden. – shmosel

0

Diese Arbeit sollte:

map.values().removeIf(Objects::isNull);