Je suis relativement nouveau sur Java8 et, dans un scénario, je dois récupérer toutes les clés de la carte qui correspondent aux objets.
Je voulais savoir s’il existait un moyen d’obtenir toutes les clés sans les réitérer de la liste.
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))
Vous pouvez également utiliser foreach api fourni dans Java8 sous lambda
Ci-dessous le code de votre méthode principale:
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);
}
});
}
Au lieu de parcourir toutes les entrées de la carte pour chaque Person
, je suggère de parcourir une fois la carte:
Set<String> keys =
inputMap.entrySet()
.stream()
.filter(e -> personOutputList.contains(e.getValue()))
.map(Map.Entry::getKey)
.collect(Collectors.toCollection(HashSet::new));
Cela entraînerait toujours un temps d'exécution quadratique (puisque List.contains()
a un temps d'exécution linéaire). Vous pouvez améliorer le temps de fonctionnement linéaire global si vous créez une HashSet
contenant les éléments de personOutputList
, car contains
pour HashSet
prend un temps constant.
Vous pouvez y parvenir en changeant
List<Person> personOutputList =
personList.stream()
.filter(p -> p.getFirstName().contains(inputCriteriaFirstName))
.collect(Collectors.toList());
à
Set<Person> personOutputSet =
personList.stream()
.filter(p -> p.getFirstName().contains(inputCriteriaFirstName))
.collect(Collectors.toCollection(HashSet::new));
Donc, vous voulez une personOutputList
avec toutes les personnes sélectionnées et un keys
avec les clés pour ces personnes sélectionnées?
La meilleure option (pour les performances) est de ne pas ignorer les clés lors de la recherche, puis de diviser le résultat en une liste de personnes et un jeu de clés distincts.
Comme ça:
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());
L'ensemble keys
est explicitement transformé en une copie pouvant être mise à jour. Si vous n'en avez pas besoin, supprimez la copie des valeurs de clé:
Set<String> keys = tempMap.keySet();