Проблема с BiMap и LinkedHashMap от Guava
-
12-12-2019 - |
Вопрос
Возможно ли это в Гуаве,
Чтобы выполнить обратный поиск в
BiMap
для ключа и нескольких значений?Точнее, у меня есть ключ и соответствующие ему несколько значений, я хочу получить ключ из значения.Чтобы сохранить несколько значений в
LinkedHashMap
?Точнее, я хочу сохранить ключ — несколько значений в некотором порядке, чтобы я мог получить ключевую позицию в списке.
Решение
Объявление.1. Да, можно выполнить обратный поиск с помощью BiMap<K, V>
, ты просто позвони inverse
на ваше BiMap
и ты становишься перевернутым BiMap<V, K>
вид вашей BiMap
.
Пример (взято из набора тестов 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"));
}
Объявление.2. Предполагая, что вы имеете в виду «Я хочу сохранить ключ -> несколько значений [коллекции]» (Map<K, Collection<V>>
), ListMultimap
это, вероятно, то, что вы хотите, точнее ArrayListMultimap
(сохраняет порядок значений) или LinkedListMultimap
(сохраняет порядок ключей и значений).Если ваш объект будет неизменяемым, я настоятельно советую вам использовать ImmutableListMultimap
.
Вы также можете создать свою собственную реализацию Multimap
используя фабрика (немного многословно), т.е.Я использую:
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
}
P.S. Взгляни на Вики Гуавы, что объясняет оба BiMap
и Multimap
.
Другие советы
ближайший в Гуаве - Multiset
для отображения нескольких значений к ключу, но я сомневаюсь, что это удовлетворяет вашему требованию.
- Я сомневаюсь, что это хорошая идея, чтобы посмотреть ключ, используя значения (если у вас есть несколько значений, отображаемых на одну клавишу), чтобы сделать это, ваше значение должно быть уникальным и рассмотрением вашей структуры данных (которая похожа на
Map<Key, Collection<Value>
), она не можетбыть гарантированно иметь уникальные значения.
- Другой вариант с guava -
Как @Xaerxess говорит в его ответ на ваш второй вопрос, вы можете задать свой собственный ListMultimap
который использует LinkedHashMap
в качестве карты-подложки, используя Multimaps.newListMultimap
метод.
Что касается вашего первого вопроса, где у вас есть ключи, сопоставленные с несколькими значениями (т.е.а Multimap
), вы можете использовать метод Multimaps.invertFrom
чтобы создать перевернутую копию оригинала Multimap
для выполнения обратного поиска.Также вы можете создать ImmutableListMultimap
скопируйте оригинал и используйте его inverse()
метод, чтобы получить обратный метод, хотя он просто скопирует оригинал, как Multimaps.invertFrom
делает (хотя он будет кэшировать его, поэтому повторные вызовы inverse()
верните ту же копию.)
Это, вероятно, того стоит, если вы не возражаете против дополнительного потребления памяти, хотите выполнить несколько обратных поисков и вам не нужна обратная копия, чтобы оставаться в курсе изменений в оригинале, которые происходят после его создания. .Если вы просто хотите найти ключи, которые соответствуют одному конкретному значению, вы можете сделать это за одну итерацию записей, не создавая полную копию.