Быстрая примитивная int многоключевая карта?

Для проекта, над которым я работаю, я пытаюсь создать многомерную опору для больших наборов данных. У меня есть все ключи, которые я хочу использовать как intс, так что в основном, я хочу вернуть набор

( int1, int2, int3, .. intN ) -> (Aggregate1, Aggregate2, ... , AggregateM)

Я не могу использовать N-мерный массив, так как он может стать огромным и, вероятно, будет редким. Я посмотрел Trove, но у них нет многоключевой карты. Apache commons имеет многоключевую карту, но это для Objects; это, вероятно, сработает, но кажется менее интересным, как ints будет автоматически упакован в Integers и наоборот.

Кто-нибудь знает о примитивной реализации многоключевой карты? (Что сопоставляется с объектами?)

Или у кого-нибудь есть отличные советы, может быть, есть лучший подход к моей проблеме?

[edit] Время вставки менее интересно, мне нужна производительность при поиске, так как карта будет активно использоваться для поиска значений.

[edit2] Спасибо за все ответы. Мой вариант реализации - пользовательский класс, содержащий int[], неизменяемый, поэтому hashcode можно рассчитать на время строительства.

private static class MultiIntKey
{
    int[] ints;

    private int hashCode;

    MultiIntKey( int[] ints )
    {
        this.ints = ints;
        this.hashCode = Arrays.hashCode( this.ints );
    }

    @Override
    public int hashCode()
    {
        return this.hashCode;
    }

    @Override
    public boolean equals( Object obj )
    {
        if ( this == obj )
        {
            return true;
        }
        if ( obj == null )
        {
            return false;
        }
        if ( this.getClass() != obj.getClass() )
        {
            return false;
        }
        MultiIntKey other = (MultiIntKey) obj;
        if ( this.hashCode != other.hashCode )
        {
            return false;
        }
        if ( !Arrays.equals( this.ints, other.ints ) )
        {
            return false;
        }
        return true;
    }
}

4 ответа

Решение

Apache commons имеет многоключевую карту, но это для объектов; это, вероятно, сработает, но кажется менее интересным, поскольку целые числа будут автоматически упаковываться в целые числа и наоборот.

Конечно, нет смысла использовать N объекты, пытаясь избежать одного.

  • Если у вас маленькие ключи, рассмотрите возможность упаковки их в один int или же long,
  • Если они повторяются много, рассмотрим TIntObjectMap<TIntObjectMap<Value>> используя trove4j, возможно, с большей вложенностью.
  • В противном случае просто создайте тривиальный объект, инкапсулирующий все целые. Объем служебных данных составляет несколько байтов, что не так уж плохо по сравнению с 4*N, В любом случае, карта хешит большие накладные расходы...

Если ваша карта неизменна, выберите Guava's ImmutableMap, Посмотрите на гуаву Table, это только 2D, но это может помочь немного сэкономить.


Только если вы уверены, что вам нужно много оптимизировать (вы сделали какой-то тест или профилирование?) И вам не нужна полноценная карта, подумайте о своей собственной реализации, основанной на некоторых int[]где вы размещаете все ключи в последовательности. Скорее всего, вы обнаружите, что это того не стоило, но это хорошее упражнение.:D

Каждый ключ может быть:

IntBuffer.wrap(new int[] { value1, value2, value3 })

Методы hashCode, equals и compareTo для IntBuffer зависят от его содержимого, поэтому они будут работать как ключи HashMap или TreeMap. (Технически эти методы зависят от оставшихся элементов в буфере, поэтому просто убедитесь, что вы никогда не измените положение или ограничение любого из создаваемых IntBuffers.)

Единственное предостережение в том, что порядок имеет значение: IntBuffer.wrap(new int[] { 1, 2 }) не равно IntBuffer.wrap(new int[] { 2, 1 }),

Строковый ключ с (int1, int2, int3,.. intN) == (int1 + "" int2 + ""..). Intern()

так что все ключи из одной таблицы через интерна, так что очень мало новых объектов. Необходимо использовать intern каждый раз, когда вы хотите, чтобы ключ был динамическим.

Самые простые способы сделать:

  1. Конвертировать в JSON / использовать MongoDB для поиска
  2. Создайте пользовательский класс, содержащий все ключи, определите его метод хэш-кода и равно, и используйте карту
Другие вопросы по тегам