Альтернативы 2D-массивам в Java - PullRequest
1 голос
/ 26 февраля 2011

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

int[][] myArray = new int[256][256];
myArray[key1][key2] = 25;

, где key1 и key2 - ключи, которые были сгенерированы ранее динамически.Но это довольно некрасиво.Кажется, что лучший способ сделать это - использовать карту, но для этого требуется один ключ, а не два.Java изначально не поддерживает кортежи, так что я должен использовать вместо этого?(Также неудобно использовать массив в качестве ключа).

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

2D-массив в Java, проиндексированный символами

Ответы [ 3 ]

3 голосов
/ 26 февраля 2011

Что в этом страшного?Это примерно так же просто, как двумерные матрицы могут быть в Java, и это тоже быстро.

Если вы действительно хотите использовать карту, просто определите свой собственный класс Tuple для использования в качестве ключа - но убедитесьчто вы переопределяете equals() и hashCode() правильно !Я бы порекомендовал реализовать неизменяемый класс Tuple, поскольку использование изменяемых объектов в качестве ключей карты может вызвать серьезные проблемы.

Tuple.java

package q5128376;

import java.util.Arrays;

public class Tuple<T>
{
    private T[] values;
    private int hashCode;

    private Tuple(T... values)
    {
        this.values = values;
        this.hashCode = hashCode(values);
    }

    public static <T> Tuple<T> create(T... values)
    {
        return new Tuple<T>(values);
    }

    private static <T> int hashCode(T... values)
    {
        return 31 * Arrays.hashCode(values);
    }

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

    @Override
    public boolean equals(Object obj) 
    {
        if (this == obj) return true;
        if (!(obj instanceof Tuple<?>)) return false;
        Tuple<?> other = (Tuple<?>) obj;
        if (!Arrays.equals(values, other.values)) return false;
        return true;
    }
}
2 голосов
/ 26 февраля 2011

Ваше решение не кажется мне очень уродливым ... Оно очень быстрое, за счет небольшого использования памяти (64 К).

Альтернативой может быть определение класса Pairиспользовать в качестве ключа для карты.

Еще одним решением было бы определить карту, которая отображает целые значения для целочисленных отображений карты и значений int:

Map<Integer, Map<Integer, Integer>> map;

Однако для этого потребуетсясоздание большого количества объектов карты.

Лучший подход зависит от того, насколько разреженной является ваша справочная таблица.

0 голосов
/ 26 февраля 2011

Я согласен с ChrisJ , что ваш двумерный массив совсем не плох.

Вы можете иметь карту карты, например

Map<Integer, Map<Integer, Integer>> myMap;

Но это может стать еще страшнее, чем ваша идея с двумерным массивом.


Кроме того, вы можете преобразовать два ключа int в один ключ String, например

Map<String, Integer> myMap = new HashMap<String, Integer>();
int key1 = 3;
int key2 = 4;
int value = 25;
myMap.put(key1 + "/" + key2, value);

Но я рекомендую использовать решение, которое у вас есть, если вы можете гарантировать, что наибольшее значение для любой клавиши равно 255.

...