【问题标题】:How to implement a 2d array of LinkedLists如何实现链接列表的二维数组
【发布时间】:2012-12-28 19:54:03
【问题描述】:

我正在从一篇论文中实现一个算法。该论文描述了使用网格,其中每个网格方块包含一个整数链表,表示该网格方块中的对象。

我决定使用LinkedList<Integer>[][] 来实现它,这当然会给我一个generic array creation 错误。

我想不出更好的方式来表示链表网格的概念。我也明白使用LinkedList[][] 可以编译,但由于它是无类型的,所以这是不好的做法。但是,我不想使用ArrayList<ArrayList<LinkedList<Integer>>>,因为这是不可读的,至少对我来说是这样。

有没有办法在这里使用无类型的LinkedList?或者其他一些解决方案?

【问题讨论】:

  • 您需要链表吗?为什么不是二维数组?另外,为什么要使用带有嵌套 LinkedList 的 ArrayList?为什么不是其中一个?
  • 现在我很好奇,你需要哪个算法?
  • 这是一种算法,用于在二维中找到一个点的最近邻居。它将二维平面分割成一个网格,每个网格正方形中都有一个点列表。然后它只对网格中距离搜索点最近的点进行距离计算。

标签: java arrays generics collections


【解决方案1】:

列表版本

List<List<List<Integer>>> grid;

不是不可读的。要访问方格,只需

List<Integer> items = grid.get(x).get(y);

对膜没那么难。

【讨论】:

  • 好的。谢谢,我想这不是那么难看。我将对此进行重构。
【解决方案2】:

波西米亚人的答案是正确的。如果您使用Guava,一个可能的替代方法是使用ArrayTable&lt;Integer, Integer, List&lt;Integer&gt;&gt;。来自文档:

由二维数组支持的固定大小 Table 实现。

当表格被提供时,必须提供允许的行和列键 创建的。该表始终包含每个行键的映射 / 列对。给定行和列对应的值为空 除非提供了其他值。

表格的大小是恒定的:提供的数量的乘积 行键和提供的列键的数量。删除和清除 表或其视图不支持方法。这 erase(java.lang.Object, java.lang.Object)eraseAll() 方法可以 改为使用。

以下是它的用法示例:

private static final int NUM_ROWS = 20; //for example
private static final int NUM_COLS = 20; //

private static final ArrayTable<Integer, Integer, List<Integer>> TABLE =
        ArrayTable.create(
                Ranges.closed(1, NUM_ROWS).asSet(DiscreteDomains.integers()),
                Ranges.closed(1, NUM_COLS).asSet(DiscreteDomains.integers())
        );

public static List<Integer> getGridQuareList(int row, int col) {
    @Nullable List<Integer> list = TABLE.at(row, col);
    if (list == null) {
        list = Lists.newArrayList(); //or newLinkedList() if you insist
        TABLE.set(row, col, list);
    }
    return list;
}

【讨论】:

    【解决方案3】:

    我会使用嵌入的ArrayList/LinkedList。你可以做些什么来清理它,因为你知道它们将拥有什么样的泛型类型,就是将它们包装在其他一些类中。像这样:

    public class Grid {
        private List<List<List<Object>>> inner;
    
        public List<Object> objectsAtPosition(int x, int y) {
            return inner.get(x).get(y);
        }
    
        // etc
    }
    

    【讨论】:

      【解决方案4】:

      我不知道你到底为什么需要一个 3 维列表(列表的 2d 数组,考虑到 ArrayLists 实际上是一个 3d 列表/数组)。但如果你确实需要它,那么你应该使用@Bohemian 写的:

      List<List<List<Integer>>> grid;
      

      你应该考虑什么:

      向接口声明变量,而不是实现,例如:

      List<Integer> list = new ArrayList<Integer>
      

      而不是

      ArrayList<Integer> list = new ArrayList<Integer>
      

      另外,一般来说,将泛型与数组混合不是一个好主意,它会变得很糟糕。如果您不想在 java 中执行此操作,而这就是您需要以 java 方式执行的操作,正如其他人所说:

      List<List<List<Integer>>>
      

      【讨论】:

      • "考虑到 ArrayLists 真的是一个 3d 列表/数组"对不起,我对你的这部分答案有点困惑。
      • 一个二维列表数组,如果你使用 ArrayLists,是(通过接口)List>>,它是一个 3d 列表。 (如果您使用 ArrayLists,也是一个 3d 数组。) 编辑:如果您认为 List 是一个一维列表(如您所愿),那么拥有它们的 2d 数组就是一个 3d 列表。我提到 ArrayLists 是因为它们可以用作数组和/或列表,所以在这里如何称呼它们并不重要。
      • 好吧,现在说得通了。是的,我确实需要一个 3d 列表。
      【解决方案5】:

      你可以像下面这样声明一个链表的数组..但是不要忘记在你打算使用链表的时候声明,否则你会得到nullpointeexception

          LinkedList<Integer>[][] ll = new LinkedList[24][24];
          ll[0][0] = new LinkedList<>();
          ll[0][0].addFirst(3);
          System.out.println(ll[0][0].removeFirst());
      

      输出:3

      【讨论】:

        【解决方案6】:

        首先:您可能可以避免使用 LinkedList。在算法书籍中,他们不知道ArrayList,Linked List,更像是动态列表的代名词。
        几乎在所有情况下,ArrayList 都更快,尤其是对于 2D 数组,需要的内存要少得多。

        我个人在拥有固定网格和动态内容时使用数组:

        List grid[][];
        
        // init with
        grid = new ArrayList[numX][numY];
        

        这样我就有了一个对象网格。这使用更少的内存。

        这样在添加对象时会更方便:

         List list = grid[i][j];
         if (list == null) {
              list = new ArrayList();
              this.cells[i][j] = list;
         }
         list.add(obj);
        

        【讨论】:

        • @PaulBellora 它是一个 java 特性或错误,你不能创建类型列表的数组,尝试一下你会感到惊讶: ArrayList[] l = new ArrayList[10 ] 不起作用。
        • 您可能只想提一下,您的解决方案受到内存稀缺的嵌入式系统的影响。一般来说,如今,泛型集合类几乎总是比普通数组更受欢迎。
        • @PaulBellora 不适用于固定大小的网格。网格通常用于大量数据,否则不会使用网格(暴力搜索就足够了)但是对于大多数任务,你是对的,泛型是首选。此外,它不仅记忆,而且速度。在这个例子中,你对(类型化的)泛型一无所获。
        【解决方案7】:

        我决定使用 LinkedList[][] 来实现它,其中 当然给了我一个通用数组创建错误。

        我想不出更好的方式来表示网格的概念 链表。我也明白使用 LinkedList[][] 会 编译,但由于它是无类型的,因此是不好的做法。

        简单。要解决这些问题,只需这样做

        LinkedList<Integer>[][] grid = (LinkedList<Integer>[][])new LinkedList<?>[5][3];
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-11-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多