Java: составные (слоистые) карты за интерфейсом карты?

Мне нужна реализация карты, которая будет состоять из сложенных карт, которые я мог бы push() и pop(), и значения будут «добавлены» или «удалены», если они принадлежат карте, которую выталкивают/извлекают. И значения будут искаться сверху/снизу (или, опционально, снизу/сверху).

Существует ли реализация в JDK или где-либо еще?

Пример:

  • Stack
    • map4
      • foo => aaa
      • бар => 45
    • map3
      • bar => 22
    • map2
      • foo => ccc
      • баз => ууу
    • карта1

Для этого get("baz") вернет "uuu", get("foo") вернет "aaa", size() вернет 3 и т. д. Это что-то вроде прототипа наследования JavaScript.

Есть один импл. impl, который на самом деле не будет проходить через все слои каждый раз, когда я вызываю какой-либо метод. Методы чтения будут использоваться чаще, чем методы push()/pop(), поэтому при этом могут быть некоторые предварительные вычисления.


person Ondra Žižka    schedule 16.06.2013    source источник
comment
И как бы вы создали здесь внешние карты?   -  person fge    schedule 17.06.2013
comment
В JDK нет такой встроенной структуры, но было бы довольно легко написать свою реализацию, используя, скажем, LinkedList<Map<K, V>>   -  person fge    schedule 17.06.2013
comment
Вы можете использовать LinkedBlockingDeque<Map<K, V>>, если вам нужно, чтобы стек был потокобезопасным.   -  person Zim-Zam O'Pootertoot    schedule 17.06.2013
comment
Сравните со свойствами, которые могут иметь другую карту свойств в качестве значений по умолчанию.   -  person Raedwald    schedule 17.06.2013


Ответы (2)


Вы можете использовать Stack в качестве оболочки. Имейте Map‹'String, Map> (строка здесь для названия карты). Предоставьте push и pop как API. Интересная часть вашего вопроса заключается в определении push и pop? Как на самом деле будет выглядеть сигнатура этого метода? На самом деле, не очень понятно, чего вы пытаетесь достичь?

person zerocool    schedule 16.06.2013

Итак, в JDK нет такой встроенной структуры, но ее можно реализовать с помощью LinkedList, содержащего Maps.

LinkedList реализует все три из List, Queue и Deque, возможно, это немного перебор, но да ладно...

Пример кода будет следующим: однако интерфейс Map на самом деле не слушается (любопытно, как бы вы сделали здесь .equals() и .hashCode()? Даже не говоря о .clear()):

public final class StackedMap<K, V>
    implements Map<K, V>
{
    private final Map<K, V> NO_MAP = new HashMap<K, V>();
    private final LinkedList<Map<K, V>> maps = new LinkedList<>();

    private Map<K, V> currentMap = NO_MAP;

    public void push(Map<K, V> map)
    {
        maps.push(map);
        currentMap = map;
    }

    public Map<K, V> pop()
    {
        return currentMap = maps.pop();
    }

    @Override
    public V get(K key)
    {
        V ret;

        for (final Map<K, V> map: maps)
            if ((ret = map.get(key)) != null)
                break;
        return ret;
    }

    // etc
}

Не проверено и т.д.

person fge    schedule 16.06.2013
comment
Что касается LinkedList излишества, в Java есть класс Stack, но в его документации говорится, что более полный и последовательный набор операций стека LIFO предоставляется интерфейсом Deque и его реализациями, которые следует использовать вместо этого класса. - person Zim-Zam O'Pootertoot; 17.06.2013
comment
@fge как насчет иметь отношения, чем есть? Я думал, что было бы лучше сделать, учитывая вопрос - person zerocool; 17.06.2013
comment
Конечно, я могу написать это сам, но мне нужен более сложный импл, который бы не проходил через все слои каждый раз, когда я вызываю какой-либо метод. Методы чтения будут использоваться чаще, чем методы push()/pop(), поэтому во время этого могут быть некоторые предварительные вычисления. - person Ondra Žižka; 17.06.2013