Ich bin relativ neu in Java8 und habe ein Szenario, in dem ich alle Schlüssel aus der Map abrufen muss, die mit den Objekten übereinstimmen.
Wollte wissen, ob es eine Möglichkeit gibt, alle Schlüssel zu erhalten, ohne sie erneut aus der Liste zu wiederholen.
Person.Java
private String firstName;
private String lastName;
//setters and getters & constructor
MAIN Class.
String inputCriteriaFirstName = "john";
Map<String, Person> inputMap = new HashMap<>();
Collection<Person> personCollection = inputMap.values();
List<Person> personList = new ArrayList<>(personCollection);
List<Person> personOutputList = personList.stream()
.filter(p -> p.getFirstName().contains(inputCriteriaFirstName ))
.collect(Collectors.toList());
//IS There a BETTER way to DO Below ??
Set<String> keys = new HashSet<>();
for(Person person : personOutputList) {
keys.addAll(inputMap.entrySet().stream().filter(entry -> Objects.equals(entry.getValue(), person))
.map(Map.Entry::getKey).collect(Collectors.toSet()));
}
inputMap.entrySet()
.stream()
.filter(entry -> personOutputList.contains(entry.getValue()))
.map(Entry::getKey)
.collect(Collectors.toCollection(HashSet::new))
Sie können auch foreach api in Java8 unter Lambda verwenden
Nachfolgend finden Sie den Code für Ihre Hauptmethode:
public static void main() {
String inputCriteriaFirstName = "john";
Map<String, Person> inputMap = new HashMap<>();
Set<String> keys = new HashSet<>();
inputMap.forEach((key,value) -> {
if(value.getFirstName().contains(inputCriteriaFirstName)){
keys.add(key);
}
});
}
Anstatt alle Einträge der Map für jede Person
zu durchlaufen, schlage ich vor, die Map einmal zu durchlaufen:
Set<String> keys =
inputMap.entrySet()
.stream()
.filter(e -> personOutputList.contains(e.getValue()))
.map(Map.Entry::getKey)
.collect(Collectors.toCollection(HashSet::new));
Dies würde immer noch zu einer quadratischen Laufzeit führen (da List.contains()
eine lineare Laufzeit hat). Sie können die lineare Laufzeit insgesamt verbessern, wenn Sie eine HashSet
mit den Elementen von personOutputList
erstellen, da contains
für HashSet
eine konstante Zeit benötigt.
Das können Sie durch Veränderung erreichen
List<Person> personOutputList =
personList.stream()
.filter(p -> p.getFirstName().contains(inputCriteriaFirstName))
.collect(Collectors.toList());
zu
Set<Person> personOutputSet =
personList.stream()
.filter(p -> p.getFirstName().contains(inputCriteriaFirstName))
.collect(Collectors.toCollection(HashSet::new));
Sie möchten also ein personOutputList
mit allen ausgewählten Personen und ein keys
mit den Schlüsseln für diese ausgewählten Personen?
Die beste Option (für die Leistung) besteht darin, die Schlüssel während der Suche nicht zu löschen und das Ergebnis in eine separate Personenliste und einen Schlüsselsatz aufzuteilen.
So was:
String inputCriteriaFirstName = "john";
Map<String, Person> inputMap = new HashMap<>();
Map<String, Person> tempMap = inputMap.entrySet()
.stream()
.filter(e -> e.getValue().getFirstName().contains(inputCriteriaFirstName))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
List<Person> personOutputList = new ArrayList<>(tempMap.values());
Set<String> keys = new HashSet<>(tempMap.keySet());
Die keys
-Gruppe wird explizit als aktualisierbare Kopie erstellt. Wenn Sie das nicht benötigen, löschen Sie das Kopieren der Schlüsselwerte:
Set<String> keys = tempMap.keySet();