Obter a chave para um valor em um mapa Java
1. Introdução
In this quick tutorial, we’re going to demonstrate three different approaches for retrieving the key from a map for a given value. Também discutiremos os pontos positivos e negativos das várias soluções.
Para saber mais sobre a interfaceMap, você pode verificarthis article.
2. Uma abordagem iterativa
A interfaceMap deJava Collections oferece um método chamadoentrySet(). Ele retorna todas as entradas ou pares de valores-chave do mapa emSet.
A ideia é iterar sobre esse conjunto de entrada e retornar a chave para a qual o valor corresponde ao valor fornecido:
public K getKey(Map map, V value) {
for (Entry entry : map.entrySet()) {
if (entry.getValue().equals(value)) {
return entry.getKey();
}
}
return null;
}
No entanto, pode haver uma possibilidade de várias chaves estarem apontando para o mesmo valor.
Nesse caso, se um valor correspondente for encontrado, adicionamos a chave aSete continuamos o loop. No final, retornamos oSet contendo todas as chaves desejadas:
public Set getKeys(Map map, V value) {
Set keys = new HashSet<>();
for (Entry entry : map.entrySet()) {
if (entry.getValue().equals(value)) {
keys.add(entry.getKey());
}
}
return keys;
}
Embora esta seja uma implementação muito direta,it compares all the entries even if all matches are found after a few iterations.
3. Uma abordagem funcional
With the introduction of Lambda Expressions in Java 8, we can do it in a more flexible and readable way. Convertemos o conjunto de entradas emStreame fornecemos um lambda para filtrar apenas as entradas com o valor fornecido.
Em seguida, usamos o método map para retornarStream das chaves das entradas filtradas:
public Stream keys(Map map, V value) {
return map
.entrySet()
.stream()
.filter(entry -> value.equals(entry.getValue()))
.map(Map.Entry::getKey);
}
The advantage of returning a stream is that it can cater to a wide range of client needs. O código de chamada pode exigir apenas uma tecla ou todas as teclas apontando para o valor fornecido. Como a avaliação de um fluxo é lenta, o cliente pode controlar o número de iterações com base em seus requisitos.
Além disso, o cliente pode converter o fluxo em qualquer coleção usando um coletor apropriado:
Stream keyStream1 = keys(capitalCountryMap, "South Africa");
String capital = keyStream1.findFirst().get();
Stream keyStream2 = keys(capitalCountryMap, "South Africa");
Set capitals = keyStream2.collect(Collectors.toSet());
4. Usando coleções do Apache Commons
As ideias acima não seriam muito úteisif we need to call the functions very frequently for a particular map. Iterará desnecessariamente o conjunto de suas chaves repetidamente.
Neste cenário,maintaining another map of value to the keys would make more sense as it will take constant time to retrieve the key for a value.
A bibliotecaCommons Collections porApache fornece umMap bidirecional chamadoBidiMap. Ele tem um método chamadogetKey() para recuperar uma chave para um determinado valor:
BidiMap capitalCountryMap = new DualHashBidiMap<>();
capitalCountryMap.put("Berlin", "Germany");
capitalCountryMap.put("Cape Town", "South Africa");
String capitalOfGermany = capitalCountryMap.getKey("Germany");
No entanto,BidiMap imposes a 1:1 relationship between its keys and values. Se tentarmos colocar um par de valores-chave para o qual o valor já existe emMap,, ele remove a entrada antiga. Em outras palavras, ele atualiza a chave com relação ao valor.
Além disso, requer uma quantidade maior de memória para manter o mapa reverso.
Mais detalhes sobre como usar umBidiMap estão emthis tutorial.
5. Usando o Google Guava
We may use another bi-directional Map called BiMap found in Guava developed by Google. Esta classe fornece um método chamadoinverse() para obter a chave de valorMap ou oMap reverso para obter a chave com base em um determinado valor:
HashBiMap capitalCountryMap = HashBiMap.create();
capitalCountryMap.put("Berlin", "Germany");
capitalCountryMap.put("Cape Town", "South Africa");
String capitalOfGermany = capitalCountryMap.inverse().get("Germany");
ComoBidiMap,BiMap also doesn’t allow multiple keys referring to the same value. Se tentarmos fazersuch an attempt, it lançar umjava.lang.IllegalArgumentException.
Não é preciso dizer queBiMap também usa uma quantidade significativa de memória, pois precisa armazenar o mapa inverso dentro. Se você estiver interessado em saber mais sobreBiMap, você pode verificarthis tutorial.
6. Conclusão
Neste breve artigo, discutimos alguns métodos de recuperação de uma chaveMap’s dado o valor. Cada abordagem tem seus próprios prós e contras. Sempre devemos considerar os casos de uso e escolher o mais apropriado com base na situação.
O código-fonte completo para o tutorial acima está disponívelover on GitHub.