Получение EntrySet в MultiMap

У меня есть MultiMap, и мне нужен наилучший способ получить EntrySet MultiMap, используя одно из значений в списке. Прямо сейчас я перебираю набор записей всей карты и проверяю, содержит ли значение списка нужные мне значения. Это работает для ограниченного количества входов на карте, но теперь это превратилось в 800 мс - 1 секунду работы, что просто не сократит его. Спасибо за помощь в продвинутом.

Пример:

public static void main(String[] args) {
        MultiMap multi = new MultiHashMap();
        multi.put("Key1", new ArrayList<String>(Arrays.asList(new String[] { "Value1", "Value2", "Value3" })));
}

Я хочу иметь возможность получать Key1, Value1, Value2 и Value3, вводя только Value1 и Value2 в качестве аргументов.

Кроме того, если это поможет, это из кеша после чтения источника данных.


person pqqqqq    schedule 19.10.2011    source источник


Ответы (2)


[Отредактировано для одновременной проверки группы значений]

[Отредактировано снова, теперь, когда вопрос прояснился]

Эта реализация избегает явных циклов и написана более функционально с использованием расширений Guava:

import java.util.Collection;
import java.util.Map.Entry;

import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;

public class TestIt {

    public static Iterable<Entry<Integer, String>> getEntrySetsForValues(
            Multimap<Integer, String> fromMap, final Collection<String> values) {
        return Iterables.filter(fromMap.entries(),
                new Predicate<Entry<Integer, String>>() {
                    @Override
                    public boolean apply(Entry<Integer, String> arg0) {
                        return values.contains(arg0.getValue());
                    }
                });
    }
}

Тестовая программа:

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;

public class Test {

    static Multimap<Integer, String> x = HashMultimap.create();

    public static void main(String[] args) {
        x.put(1, "a");
        x.put(1, "b");
        x.put(2, "d");
        x.put(3, "e");
        x.put(3, "f");
        x.put(4, "a");
        x.put(5, "b");
        x.put(5, "c");

        System.out.println(TestIt.getEntrySetsForValues(x,
                Sets.newHashSet("a", "c")));
    }
}

Выход:

[1=a, 4=a, 5=c]

Мне было бы любопытно узнать, насколько это неэффективно.

person Steve J    schedule 19.10.2011
comment
Это почти удивительно, но единственная проблема в том, что мне нужно, чтобы запись имела оба определенных значения, а не или или. Но это потрясающе (еще не проверял время работы, эффективность) - person pqqqqq; 19.10.2011
comment
Спасибо. Вы можете легко изменить это, чтобы дать вам записи, или только ключи, или что-то еще. - person Steve J; 19.10.2011

Пробовали ли вы использовать коллекции Apache Common? у них есть реализация multimap, которая может вам помочь, в частности метод containsValue.

Предполагая, что в значениях нет повторяющихся элементов, вы можете использовать Set для хранения нескольких значений и ускорения поиска. Просто (непроверенная) идея, что-то вроде этого:

public static <K, V> Map.Entry<K, Set<V>> getEntry(Map<K,Set<V>> map, Set<V> vals) {
    for (Map.Entry<K, Set<V>> entry : map.entrySet()) {
        boolean found = true;
        for (V val : vals) {
            if (!entry.getValue().contains(val)) {
                found = false;
                break;
            }
        }
        if (found)
            return entry;
    }
    return null;
}
person Óscar López    schedule 19.10.2011
comment
У меня есть, но моя проблема в том, что мне нужно получить всю коллекцию и ключ, используя около 4 значений коллекции. Конечно, единственное, о чем я могу думать, это итерация. - person pqqqqq; 19.10.2011
comment
Это хорошо, но я уже делаю примерно то же самое. Слишком много значений для итерации (более 10 тыс.) - person pqqqqq; 19.10.2011
comment
Проверьте, соответствует ли моя приведенная выше реализация вашим требованиям: она получает мультикарту и набор искомых значений и возвращает пару ключей, значений. - person Óscar López; 19.10.2011
comment
Я знаю, что это, вероятно, сработает, но меня беспокоит время и эффективность. Я думаю, что я нашел что-то, спасибо большое за все равно! - person pqqqqq; 19.10.2011