开发者

How to make an 2D ArrayList immutable?

开发者 https://www.devze.com 2023-03-14 20:51 出处:网络
In the project I am working on, I have a 2D ArrayList which represents some data开发者_开发百科:

In the project I am working on, I have a 2D ArrayList which represents some data开发者_开发百科:

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

Now I need to return this ArrayList to some object, in order to let the object inspect it, but not modify it.

I found in the following post that a 2D ArrayList needs to be wrapped separately by the unmodifiable wrapper, but it does not mention how to do it:

Does the unmodifiable wrapper for java collections make them thread safe?

So my problem is: how to return an immutable 2D ArrayList from an existing 2D ArrayList? And in addition, what is the fastest way, since the data could be large in practice?

Thanks for all the inputs!


Use the Collections.unmodifiableList method:

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

Calling Collections.unmodifiableList on the source collection, does not make each nested list unmodifiable. You'll need to do this recursively on the list, if you want all nested lists to be unmodifiable. So:

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);    


I'd recommend creating a wrapper class which handles the mutability issues rather than having List<List<T>> all over the code-base. You can make this class implement the List interface so the clients can actually use it as a list but the underlying data need not necessarily be a list of lists (it can even be an array or arrays).

Using an array internally will save you through the trouble of stepping through a list of lists which might even end up increasing performance. You can also try looking at one of the numeric Java libraries out there and see if they offer a immutable high performance matrix, unless this class is just a small part of your application and you won't be needing anything more.


You can write your own immutable matrix wrapper.

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();
    }

}

As I wrote in the code, maybe you want to swap x and y.
Or rename them as level0 and level1.

This way, you don't have to copy anything. This is sufficient:

public Matrix<T> returnInspectData()
{
     return new Matrix(data); 
}


Assuming a list of lists is the best way to represent your data:

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);

Running time is O(n) for an array of size n by m


A list of lists is a decent way to perform ad-hoc data collection on irregularly populated matrixes, but if you're actually dealing with regular, 2D arrays of fixed size, it makes sense to create a wrapper object around a backing String[][], and move your business logic that creates and manipulates that data into that object. This includes returning a read-only view of your matrix, and if you have a function that is expecting a read-only List<List<String>>, you can return an view object that implements that interface from the backing arrays.


You might use Collections.unmodifiableList( ... ) which does what you want. However, that works for one list only, so you'd have to do that for the inner lists as well.

Another option might be a 2D array. Besides that, you might to use a wrapper class as has already been suggested.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号