Несколько индексов для коллекции Java - самое основное решение? - PullRequest
47 голосов
/ 23 марта 2010

Я ищу самое простое решение для создания нескольких индексов в коллекции Java.

Требуемая функциональность:

  • При удалении значения все записи индекса, связанные с этим значением, должны быть удалены.
  • Поиск по индексу должен быть быстрее, чем линейный поиск (по крайней мере, так же быстро, как TreeMap).

Боковые условия:

  • Нет зависимости от больших (например, Lucene) библиотек. Нет необычных или плохо проверенных библиотек. Нет базы данных.
  • Библиотека вроде Apache Commons Collections и т. Д. Будет в порядке.
  • Еще лучше, если он работает только с JavaSE (6.0).
  • Редактировать: Нет самостоятельного решения (спасибо за ответы, предлагающие это - хорошо, что они здесь для полноты, но у меня уже есть решение, очень похожее на решение Джея) Всякий раз, когда несколько человек узнайте, что они реализовали одно и то же, это должно быть частью какой-то общей библиотеки.

Конечно, я мог бы написать класс, который управляет несколькими Картами самостоятельно (это не сложно, но похоже на изобретение колеса) . Поэтому я хотел бы знать, можно ли это сделать без - при этом получая простое использование, похожее на использование одного индексированного java.util.Map.

Спасибо, Крис

Обновление

Очень похоже, что мы ничего не нашли. Мне нравятся все ваши ответы - самостоятельно разработанные версии, ссылки на библиотеки, подобные базам данных.

Вот что я действительно хочу: иметь функциональность в (a) Коллекциях Apache Commons или (b) в Google Collections / Guava. Или, может быть, очень хорошая альтернатива.

Неужели другие люди тоже пропускают эту функцию в этих библиотеках? Они предоставляют всевозможные вещи, такие как MultiMaps, MulitKeyMaps, BidiMaps, ... Я чувствую, что это прекрасно вписалось бы в эти библиотеки - его можно назвать MultiIndexMap. Что ты думаешь?

Ответы [ 14 ]

0 голосов
/ 11 апреля 2017

Вот как я это делаю, сейчас только методы put, remove и get работают для отдыха, вам нужно переопределить нужные методы.

Пример:

MultiKeyMap<MultiKeyMap.Key,String> map = new MultiKeyMap<>();
MultiKeyMap.Key key1 = map.generatePrimaryKey("keyA","keyB","keyC");
MultiKeyMap.Key key2 = map.generatePrimaryKey("keyD","keyE","keyF");

map.put(key1,"This is value 1");
map.put(key2,"This is value 2");

Log.i("MultiKeyMapDebug",map.get("keyA"));
Log.i("MultiKeyMapDebug",map.get("keyB"));
Log.i("MultiKeyMapDebug",map.get("keyC"));

Log.i("MultiKeyMapDebug",""+map.get("keyD"));
Log.i("MultiKeyMapDebug",""+map.get("keyE"));
Log.i("MultiKeyMapDebug",""+map.get("keyF"));

Выход:

MultiKeyMapDebug: This is value 1
MultiKeyMapDebug: This is value 1
MultiKeyMapDebug: This is value 1
MultiKeyMapDebug: This is value 2
MultiKeyMapDebug: This is value 2
MultiKeyMapDebug: This is value 2

MultiKeyMap.java:

/**
 * Created by hsn on 11/04/17.
 */


public class MultiKeyMap<K extends MultiKeyMap.Key, V> extends HashMap<MultiKeyMap.Key, V> {

    private Map<String, MultiKeyMap.Key> keyMap = new HashMap<>();

    @Override
    public V get(Object key) {
        return super.get(keyMap.get(key));
    }

    @Override
    public V put(MultiKeyMap.Key key, V value) {
        List<String> keyArray = (List<String>) key;
        for (String keyS : keyArray) {
            keyMap.put(keyS, key);
        }
        return super.put(key, value);
    }

    @Override
    public V remove(Object key) {
        return super.remove(keyMap.get(key));
    }

    public Key generatePrimaryKey(String... keys) {
        Key singleKey = new Key();
        for (String key : keys) {
            singleKey.add(key);
        }
        return singleKey;
    }

    public class Key extends ArrayList<String> {

    }

}
0 голосов
/ 19 апреля 2013

По сути, было бы возможно решение, основанное на нескольких хэш-картах, но в этом случае все они должны обновляться вручную Очень простое интегрированное решение можно найти здесь: http://insidecoffe.blogspot.de/2013/04/indexable-hashmap-implementation.html

0 голосов
/ 22 марта 2011

давайте посмотрим на проект http://code.google.com/p/multiindexcontainer/wiki/MainPage Это обобщенный способ использования карт для геттеров JavaBean и выполнения поиска по индексированным значениям. Я думаю, это то, что вы ищете. Давайте попробуем.

0 голосов
/ 30 марта 2010

Я не уверен, что понимаю вопрос, но думаю, что вам нужно несколько способов сопоставления различных уникальных ключей со значениями и соответствующей очистки при исчезновении значения.

Я вижу, что вы не хотите бросать свои собственные, но есть достаточно простая композиция карты и мультикарты (я использовал мультикарту Guava ниже, но Apache тоже должен работать), чтобы делать то, что вы хотите. У меня есть быстрое и грязное решение ниже (пропущенные конструкторы, так как это зависит от того, какую карту / мультикарту вы хотите использовать):

package edu.cap10.common.collect;

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

import com.google.common.collect.ForwardingMap;
import com.google.common.collect.Multimap;

public class MIndexLookupMap<T> extends ForwardingMap<Object,T>{

    Map<Object,T> delegate;
    Multimap<T,Object> reverse;

    @Override protected Map<Object, T> delegate() { return delegate; }

    @Override public void clear() {
        delegate.clear();
        reverse.clear();
    }

    @Override public boolean containsValue(Object value) { return reverse.containsKey(value); }

    @Override public T put(Object key, T value) {
        if (containsKey(key) && !get(key).equals(value)) reverse.remove(get(key), key); 
        reverse.put(value, key);
        return delegate.put(key, value);
    }

    @Override public void putAll(Map<? extends Object, ? extends T> m) {
        for (Entry<? extends Object,? extends T> e : m.entrySet()) put(e.getKey(),e.getValue());
    }

    public T remove(Object key) {
        T result = delegate.remove(key);
        reverse.remove(result, key);
        return result;
    }

    public void removeValue(T value) {
        for (Object key : reverse.removeAll(value)) delegate.remove(key);
    }

    public Collection<T> values() {
        return reverse.keySet();
    }   

}

удаление - это O (количество ключей), но все остальное в том же порядке, что и типичная реализация карты (некоторое дополнительное постоянное масштабирование, так как вы также должны добавлять вещи к обратному).

Я только что использовал Object ключи (должно быть в порядке с соответствующими реализациями equals() и hashCode() и различием ключей) - но вы могли бы также иметь более конкретный тип ключа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...