Как сделать 2D ArrayList неизменным? - PullRequest
5 голосов
/ 22 июня 2011

В проекте, над которым я работаю, у меня есть 2D ArrayList, который представляет некоторые данные:

private ArrayList<ArrayList<T>> data = null;

Теперь мне нужно вернуть этот ArrayList некоторому объекту, чтобыпусть объект проверяет его, но не изменяет его.

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

Делает ли немодифицируемая оболочка для коллекций java потокобезопасными?

Итак, моя проблема: как вернуть неизменяемый 2D ArrayList из существующего 2D ArrayList?И, кроме того, какой самый быстрый способ, поскольку на практике данные могут быть большими?

Спасибо за все входные данные!

Ответы [ 5 ]

1 голос
/ 22 июня 2011

Предполагая, что список списков - лучший способ представить ваши данные:

private ArrayList<ArrayList<T>> data = (put your data here);


ArrayList<ArrayList<String>> temp = new ArrayList<ArrayList<String>>();
for (ArrayList<String> l : data) {
    temp.add(Collections.unmodifiableList(l));
}
return Collections.unmodifiableList(temp);

Время выполнения O (n) для массива размера n по m


Список списков - хороший способ выполнить специальный сбор данных для нерегулярно заполненных матриц, но если вы на самом деле имеете дело с обычными двумерными массивами фиксированного размера, имеет смысл создать объект-оболочку вокруг подложки String[][]и переместите свою бизнес-логику, которая создает эти данные и манипулирует ими, в этот объект.Это включает в себя возвращение только для чтения представления вашей матрицы, и если у вас есть функция, которая ожидает только для чтения List<List<String>>, вы можете вернуть объект представления, реализующий этот интерфейс, из резервных массивов.

1 голос
/ 22 июня 2011

Используйте метод Collections.unmodifiableList:

ArrayList<ArrayList<String>> source = new ArrayList<ArrayList<String>>();
List<ArrayList<String>> out = Collections.unmodifiableList(source);

Вызов Collections.unmodifiableList в коллекции source не делает неизменным каждый вложенный список. Вам нужно будет сделать это рекурсивно в списке, если вы хотите, чтобы все вложенные списки были неизменяемыми. Итак:

ArrayList<ArrayList<String>> source = new ArrayList<ArrayList<String>>();
List<List<String>> temp = new ArrayList<List<String>>();
for (ArrayList<String> list : source) {
    temp.add(Collections.unmodifiableList(list));
}
List<List<String>> out = Collections.unmodifiableList(temp);    
1 голос
/ 22 июня 2011

Вы можете написать свою собственную неизменяемую матричную оболочку.

public class ImmutableMatrix<T>
{
    private ArrayList<ArrayList<T>> matrix;

    public ImmutableMatrix(ArrayList<ArrayList<T>> matrix)
    {
        this.matrix = matrix;
    }

    public T get(int x, int y)
    {
        return matrix.get(y).get(x); // Maybe you want to swap x and y
    }

    public int height()
    {
        return matrix.size();
    }

    public int width(int y)
    {
        return matrix.get(y).size();
    }

}

Как я уже писал в коде, возможно, вы захотите поменять местами x и y.
или переименовать их как level0 и level1.

Таким образом, вам не нужно ничего копировать.Этого достаточно:

public Matrix<T> returnInspectData()
{
     return new Matrix(data); 
}
1 голос
/ 22 июня 2011

Я бы порекомендовал создать класс-оболочку, который обрабатывает проблемы с изменяемостью, а не иметь List<List<T>> по всей базе кода.Вы можете заставить этот класс реализовывать интерфейс List, чтобы клиенты могли фактически использовать его как список, но базовые данные не обязательно должны быть списком списков (это может быть даже массив или массивы).

ИспользованиеВнутренний массив избавит вас от необходимости обходить список списков, что может даже привести к увеличению производительности.Вы также можете попробовать взглянуть на одну из числовых библиотек Java и посмотреть, предлагают ли они неизменную высокопроизводительную матрицу, если этот класс не является лишь небольшой частью вашего приложения и вам больше ничего не понадобится.

0 голосов
/ 22 июня 2011

Вы можете использовать Collections.unmodifiableList( ... ), который делает то, что вы хотите. Тем не менее, это работает только для одного списка, поэтому вам придется сделать это и для внутренних списков.

Другим вариантом может быть 2D-массив. Кроме того, вы можете использовать класс-оболочку, как уже было предложено.

...