【问题标题】:What collection to use instead of 2D array in Java?在 Java 中使用什么集合代替二维数组?
【发布时间】:2010-01-12 16:31:18
【问题描述】:

我想使用一个集合来代替二维数组,这样我就不需要在声明时给出它的大小,并且我可以动态添加任意数量的元素。

【问题讨论】:

  • 你打算使用什么模式来访问数组中的元素?随机访问、整行、整列?

标签: java collections


【解决方案1】:

List> 的问题是,如果你想重新调整矩阵的大小,就必须重新调整每一行的大小。

如果你想使用稀疏矩阵,或者无限矩阵,你可以这样做:

class SparseMatrix<X> {
  private Map<Coord, X> values = new HashMap<Coord, X>();

  public SparseMatrix() {
  }

  public X get(int x, int y) {
     return values.put(new Coord(x,y)); // null if there's no value
  }

  public void set(int x, int y, X value) { // you can use null (like in a List)
     values.set(new Coord(x,y), value);
  }

  private static class Coord {
    int x; int y;
    public Coord(int x, int y) {
       this.x = x;
       this.y = y;
    }

    @Override
    public boolean equals(Object other) {
       if (other instance of Coord) {
          Coord o = (Coord) other;
          return o.x == x && o.y == y;
       }
       return false;
    }

    @Override
    public int hashCode() {
       return o.x + o.y; // or some more clever implementation :)
    }

  }
}

编辑:Apache Commons HashCodeBuilder 是生成哈希码的好工具。

【讨论】:

  • 您的 hashCode 可能会溢出 - 但是您 确实 已相应地对其进行了评论... :)
  • 锐利的观点!!!有一个实用方法:java.util.Arrays.hashCode(int[]) 可以为 int[] 创建一个哈希码,但是当然,每次需要 hashChode 时(或有它创建)。也许我们可以只复制两个整数的实现:(31 + o.x) * 31 + o.y。但它似乎无论如何都会溢出......(我认为这并不重要,它是循环的吗?)。
  • 在 hashCode() 中 x+y == y+x 是否重要?
  • 不,没关系。 hashCodes 的重要之处在于它们提供了相当分布的值,因此如果您有 N 个存储桶,您可以使用该 hashCode 或多或少均匀地分配它们(将对象 X 放入存储桶 hasCode(X) % N。这就是我的实现不好的原因:如果你使用低坐标它给出低哈希码。我将添加对Apache HashCodeBuilder的引用。它很好地封装了这个问题。
【解决方案2】:

最简单的方法是使用嵌套集合...比如说(假设您的值是字符串)List&lt;List&lt;String&gt;&gt;,然后可以这样使用:

List<List<String>> fakeArray = new ArrayList<List<String>>();

// Pretend you fill it with values between these calls
String retrieve = fakeArray.get(0).get(0);

编辑:这最初是 Map&lt;String,List&lt;String&gt;&gt;,在这种情况下确实没有意义。

但是,您可能想看看Google CollectionsApache Commons Collections 是否有更专业的东西可以使用。

【讨论】:

  • 我会删除这个“编辑”信息——现在它也没有意义了;p
【解决方案3】:

你想用它做什么?我可能会简单地使用 Collection&lt;Collection&lt;Element&gt;&gt;(其中 Collection 可能会被 List 替换)。

或者您可以创建自己的类,使用方法来迭代行或列或所有需要的元素。

【讨论】:

    【解决方案4】:

    我个人为此目的使用Vector 类,尽管不同的要求最终可能决定使用其他更专业的类。

    【讨论】:

    • Vector 已被弃用,已被 ArrayList 取代。
    • @mortiz - 通常应避免使用java.util.Vector - 它的线程安全性对于大多数多线程场景不是很有用,只会增加单线程使用的开销。大多数人使用ArrayList 作为默认的List 类型。
    【解决方案5】:

    【讨论】:

    • 我认为当我们想要动态一维数组时使用它
    • 您可以拥有一个 ArrayList,它的每个元素都是另一个 ArrayList(正如 rsp 和我在我们的答案中提出的那样)。这样一来,ArrayList 也可以用于二维数组。
    【解决方案6】:

    这取决于你想要做什么,但我会推荐 ArrayList。它比 Vector 更快。除非你关心同步!如果你希望它是一个二维列表,那么你创建一个 ArrayList,这个列表的每个元素都是另一个 ArrayList。

    【讨论】:

      【解决方案7】:

      您可以尝试使用 ArrayList 并将 ArrayLists 作为项目。如果这不能满足您的需求,它将让您深入了解自己需要构建的内容。

      【讨论】:

        【解决方案8】:

        这取决于您要使用数据结构的方式。您的选择是:

        • 两个列表;在它们之间进行同步是您的工作。
        • 地图;您的地图条目将只是对象的元组,而不是键值关系。
        • 2 单元对象数组的列表;列表中的每一项都是大小为 2 的对象数组。

        编辑: 我完全误解了这个问题;我认为这是一个宽度为 2 的二维数组。

        正确阅读了这个问题(我希望 :-)),我同意那些说列表列表的人。

        【讨论】:

          【解决方案9】:

          导入java.util.ArrayList;

          ArrayList是你想要的,你不需要在创建时设置它的大小,你可以使用add方法动态添加元素。

          【讨论】:

            猜你喜欢
            • 2011-07-04
            • 2016-07-01
            • 1970-01-01
            • 1970-01-01
            • 2012-02-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-04-29
            相关资源
            最近更新 更多