简体   繁体   English

Java:arraylists的二维数组?

[英]Java: 2D array of arraylists?

I am working on a sudoku solving program and I need an arraylist that holds the numbers 1 thru 9 for each of the squares on the 9x9 board. 我正在开发数独解决方案,并且我需要一个9x9板上每个正方形的数字1到9的数组列表。 Each of these arraylists correspond to the possible numbers that could go in that square, if a number can not go in that square, it is removed from the list. 这些数组列表中的每一个对应于可能在那个正方形中出现的数字,如果一个数字不能在那个正方形中出现,则将其从列表中删除。

I want to be able to pull up the arraylist of the current square it is working on, like for example if I wanted to remove the number 7 from the arraylist corresponding to square (3,5) 我希望能够提取正在处理的当前正方形的arraylist,例如,例如,如果我想从对应于square(3,5)的arraylist中删除数字7

arrayOfLists[3][5].remove(Integer.valueOf(7));

However I can't figure out how to do this. 但是我不知道如何做到这一点。 When I try to create the array I am getting this error on the line where I declare my array of arraylists 当我尝试创建数组时,在声明数组列表数组的行上出现此错误

Cannot create a generic array of ArrayList 无法创建ArrayList的通用数组

Here is my code: 这是我的代码:

    //create arraylist
    ArrayList<Integer> nums = new ArrayList<Integer>();

    //fill arraylist with numbers 1-9
    for (int i = 1; i < 10; i++) {
        nums.add(i);
    }

    //create 9x9 array of arraylists
    ArrayList<Integer>[][] array = new ArrayList<Integer>[9][9];

    //fill each element of array with arraylist of numbers 1-9
    for(int i = 0; i<9; i++){
        for(int j = 0; j<9; j++){
            array[i][j] = nums;
        }       
    }

}

Am I doing this incorrectly or is it not possible to create an array of arraylists? 我这样做有误还是无法创建arraylists数组? If it is not possible, how should I do this then? 如果不可能,那我该怎么办呢?

Anytime I see a list of lists, alarm bells start ringing. 每当我看到列表列表时,警钟就会响起。 The situations where you actually want such a thing are rare indeed, and this is not one of them. 实际上,您真正想要这样的事情的情况确实很少见,而这并不是其中之一。

You've got a fixed board consisting of 9 fixed squares, columns and rows, each position of which may take a number 1-9. 您有一个由9个固定的正方形,列和行组成的固定板,每个位置可能需要1-9的数字。

Use an array for all of these concepts, because they are fixed in size and you need direct access to each element - collections offer no benefit and would be a hindrance. 对所有这些概念都使用数组,因为它们的大小是固定的,并且您需要直接访问每个元素-集合没有好处,而且会成为一个障碍。 Use logic (possibly sets) to ensure numbers are used only once in each zone. 使用逻辑(可能是一组)来确保数字在每个区域中仅使用一次。

Use a bit field instead of an array list. 使用位字段而不是数组列表。 That is, use an integer where bits 1-9 represent the possibilities of the numbers. 即,使用整数,其中位1-9代表数字的可能性。 Testing, adding, removing a single number is O(1), and it has a fixed memory size. 测试,添加和删除单个数字是O(1),并且它具有固定的内存大小。 Encapsulate the integer in its own object that knows the operations. 将整数封装在自己的知道操作的对象中。

A few things: 一些东西:

1) In your for loop, array[i][j] = nums; 1)在您的for循环中,array [i] [j] = nums; This is going to result in the same object in each element of the array. 这将在数​​组的每个元素中导致相同的对象。 If you call remove() on one element of the array, it's going to affect all the others. 如果在数组的一个元素上调用remove(),它将影响所有其他元素。 You want to build a separate list object for each element. 您要为每个元素构建一个单独的列表对象。

2) Program to interfaces; 2)编程接口; declare nums as a List as opposed to ArrayList. 将nums声明为List,而不是ArrayList。

3) Use a List of Lists as opposed to any array of Lists. 3)使用列表列表,而不是任何列表数组。

    List<List<List<Integer>>> list = new ArrayList<List<List<Integer>>>();
    for(int i = 0; i<9; i++){
        List<List<Integer>> row = new ArrayList<List<Integer>>();
        for(int j = 0; j<9; j++){
            List<Integer> nums = new ArrayList<Integer>();
            for (int k = 1; k < 10; k++) {
                nums.add(i);
            }
            row.add(nums);
        }
        list.add(row);
    }

    // You can still get an element by index
    int x = list.get(3).get(1).remove(6);

But this is kind of unwieldy. 但这有点笨拙。 You might want to consider writing a class that represents the board. 您可能需要考虑编写一个代表董事会的课程。 That way you'll at least have operations that better abstract this. 这样,您至少将拥有可以更好地对此进行抽象的操作。

You could completely remove the use 2d stuff and keep a single list by giving each square a unique number from 1...81. 您可以完全删除使用2d的内容,并通过为每个方块指定一个从1 ... 81开始的唯一编号来保留单个列表。 So if you are working with 3,5 cell that means it's the 9*2+5 = 23rd item in the list. 因此,如果您使用的是3,5单元格,则意味着它是列表中的9 * 2 + 5 = 23rd项。 That will greatly simplify the list manipulation. 这将大大简化列表操作。 You could use a single method to give the unique cell index given the (3,5) kind of reference 给定(3,5)类型的引用,您可以使用一种方法来提供唯一的单元格索引

OK, I'm going to post this as an answer since it seems to work for me and I haven't yet seen any pitfalls. 好的,我将其发布为答案,因为它似乎对我有用,而且我还没有发现任何陷阱。

private static class IntegerArrayList extends ArrayList<Integer> {
    IntegerArrayList () { super(); }
    IntegerArrayList (Collection<? extends Integer> c) { super(c); }
    IntegerArrayList (int initialCapacity) { super(initialCapacity); }
}

Now you can say something like 现在你可以说类似

IntegerArrayList[][] array = new IntegerArrayList[9][9];

and elements like array[1][2] will inherit all the ArrayList methods ( array[1][2].remove(something) works fine). 并且诸如array [1] [2]之类的元素将继承所有ArrayList方法( array[1][2].remove(something)正常工作)。 I made the class private static thinking you could nest it in some other class if that's the only place you'll use it, but you can make it public if you like. 我将类private static以为您可以在其他唯一的类中嵌套它,但是可以根据需要将其公开。 Also, I copied all three constructors from ArrayList ; 另外,我从ArrayList复制了所有三个构造函数; you could eliminate unneeded ones but I don't see a compelling reason to. 您可以消除不需要的,但是我没有令人信服的理由。

I think the issue is that new ArrayList<Integer>[9][9] is prohibited because it would create an array that wouldn't do type checking (because of "type erasure"). 我认为问题是禁止使用new ArrayList<Integer>[9][9] ,因为它会创建一个不会进行类型检查的数组(因为“类型擦除”)。 But I think adding your own non-generic type that inherits from ArrayList<Integer> restores the type safety. 但是我认为添加您自己的从ArrayList<Integer>继承的非泛型类型可以恢复类型安全性。

But I'm not a generic expert, and it wouldn't surprise me if someone more knowledgeable than I spots a problem with this solution. 但是我不是一般的专家,如果比我更有知识的人发现此解决方案有问题,也不会感到惊讶。 But it seemed to work fine for me, with no compiler warnings about unchecked type stuff or anything. 但这似乎对我来说很好用,没有编译器警告未检查的类型的东西。

(PS I'm posting this as a possible general solution to a problem that gets asked a lot. But in reality, for this particular problem, I might just use a fixed-size array of boolean instead of an ArrayList, like others, or I might even do bit-diddling on integers if speed is a real issue.) (PS我将其发布为一个可能会引起很多问题的通用解决方案。但是实际上,对于这个特定问题,我可能只使用固定大小的布尔数组而不是ArrayList,就像其他数组一样,或者如果速度是一个真正的问题,我什至可以对整数进行位运算。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM