如何使2D ArrayList不可变?

时间:2011-06-22 14:21:03

标签: java arraylist 2d wrapper immutability

在我正在研究的项目中,我有一个代表一些数据的2D ArrayList:

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

现在我需要将这个ArrayList返回给某个对象,以便让对象检查它,但不要修改它。

我在下面的帖子中发现2D ArrayList需要由不可修改的包装器单独包装,但它没有提到如何操作:

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

所以我的问题是:如何从现有的2D ArrayList返回不可变的2D ArrayList?另外,最快的方法是什么,因为实际数据可能很大?

感谢所有的投入!

5 个答案:

答案 0 :(得分:1)

我建议创建一个包装类来处理可变性问题,而不是在整个代码库中使用List<List<T>>。您可以使此类实现List接口,以便客户端实际上可以将其用作列表,但基础数据不一定是列表列表(它甚至可以是数组或数组)。

在内部使用数组可以省去踩到列表列表的麻烦,这些列表最终可能会提高性能。你也可以尝试查看其中一个数字Java库,看看它们是否提供了一个不可变的高性能矩阵,除非这个类只是你应用程序的一小部分,你不再需要它。

答案 1 :(得分:1)

您可以编写自己的不可变矩阵包装器。

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

}

正如我在代码中所写,也许您想要交换xy 或者将其重命名为level0level1

这样,您无需复制任何内容。这就足够了:

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

答案 2 :(得分:1)

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

答案 3 :(得分:1)

假设列表列表是表示数据的最佳方式:

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

对于大小为n乘以m

的数组,运行时间为O(n)

列表列表是在不规则填充的矩阵上执行临时数据收集的一种不错的方法,但如果您实际处理固定大小的常规2D数组,则在后台周围创建包装器对象是有意义的String[][],并将创建和操作该数据的业务逻辑移动到该对象中。这包括返回矩阵的只读视图,如果您有一个期望只读List<List<String>>的函数,则可以从支持数组返回实现该接口的视图对象。

答案 4 :(得分:0)

您可以使用符合您需要的Collections.unmodifiableList( ... )。但是,这仅适用于一个列表,因此您也必须为内部列表执行此操作。

另一个选项可能是2D数组。除此之外,您可以使用已经建议的包装类。