Problema con BiMap y LinkedHashMap de Guava
-
12-12-2019 - |
Pregunta
¿Es posible en guayaba,
Para realizar una búsqueda inversa en
BiMap
para valores clave y múltiples?Precisamente, tengo la clave y los valores múltiples correspondientes, quiero obtener la clave de un valor.Para almacenar múltiples valores en
LinkedHashMap
?Precisamente, quiero almacenar claves: múltiples valores en algún orden para poder obtener la posición clave en la lista.
Solución
Anuncio.1. Sí, es posible hacer una búsqueda inversa con un BiMap<K, V>
, solo llamas inverse
en tu BiMap
y te inviertes BiMap<V, K>
vista de tu BiMap
.
Ejemplo (tomado del conjunto de pruebas de Guava):
public void testMapConstructor() {
/* Test with non-empty Map. */
Map<String, String> map = ImmutableMap.of(
"canada", "dollar",
"chile", "peso",
"switzerland", "franc");
HashBiMap<String, String> bimap = HashBiMap.create(map);
assertEquals("dollar", bimap.get("canada"));
assertEquals("canada", bimap.inverse().get("dollar"));
}
Anuncio.2. Suponiendo que te refieres "Quiero almacenar clave -> múltiples valores de [colección]" (Map<K, Collection<V>>
), ListMultimap
es probablemente lo que quieres, más precisamente ArrayListMultimap
(conserva el orden de los valores) o LinkedListMultimap
(conserva el orden de claves y valores).Si su objeto va a ser inmutable, le recomiendo encarecidamente que utilice ImmutableListMultimap
.
También puedes crear tu propia implementación de Multimap
mediante el uso fábrica (poco detallado), es decirYo suelo:
private static <K, V> ListMultimap<K, V> makeLinkedArrayListMultimap() {
return Multimaps.newListMultimap(Maps.<K, Collection<V>>newLinkedHashMap(),
new Supplier<List<V>>() {
@Override public List<V> get() {
return Lists.newArrayList();
}
});
}
public static void main(final String[] args) {
final ListMultimap<String, String> multimap = makeLinkedArrayListMultimap();
multimap.putAll("one", ImmutableList.of("zero", "three"));
multimap.putAll("two", ImmutableList.of("three", "four", "three"));
multimap.putAll("three", ImmutableList.<String>of()); // note that this doesn't add key to multimap
multimap.put("four", "forty-two");
System.out.println(multimap);
// prints {one=[one, three], two=[three, four, three], four=[forty-two]}
final List<String> listForOnes = multimap.get("one");
System.out.println(listForOnes.get(0));
// prints zero
}
PD Echa un vistazo a Wiki de guayaba, lo que explica ambos BiMap
y Multimap
.
Otros consejos
El más cercano en Guayaba es Multiset
para asignar múltiples valores a la clave, pero dudo que satisfaga sus requisitos.
- Dudo que sea una buena idea buscar claves usando valores (cuando tienes múltiples valores asignados a una sola clave), para hacer esto tu valor debe ser único y considerando tu estructura de datos (que es como
Map<Key, Collection<Value>
) no se puede garantizar que tenga valores únicos. - La otra opción con guayaba es
BiMap
lo que requiere valores únicos y puede proporcionar asignaciones inversas (valor -> clave), pero dado que necesita asignar varios valores a la misma clave, esto tampoco es una buena opción.
Como @Xaerxess dice en su respuesta a tu segunda pregunta, puedes hacer la tuya propia ListMultimap
que usa un LinkedHashMap
como mapa de respaldo usando el Multimaps.newListMultimap
método.
Para su primera pregunta, donde tiene claves asignadas a múltiples valores (es decir,a Multimap
), puedes usar el método Multimaps.invertFrom
para crear una copia invertida de su original Multimap
para realizar búsquedas inversas.Además, puedes crear un ImmutableListMultimap
copia del original y utilizar su inverse()
método para obtener lo inverso, aunque eso solo copiará el original tal como Multimaps.invertFrom
lo hace (aunque lo almacenará en caché para que las llamadas repetidas a inverse()
devolver la misma copia.)
Probablemente valga la pena si no le importa el consumo adicional de memoria, desea realizar múltiples búsquedas inversas y no necesita la copia inversa para mantenerse actualizado con los cambios en el original que ocurren después de crearlo. .Si solo desea buscar las claves que se asignan a un valor específico, puede hacerlo en una iteración de las entradas sin crear una copia completa.