【问题标题】:Java data structure that only indexes identical items onceJava 数据结构,只索引相同的项目一次
【发布时间】:2011-05-26 23:04:12
【问题描述】:

以下Java代码:

public static void main(String args[]) {

    int[] x = new int[] {1, 2, 3};
    int[] y = new int[] {1, 2, 3};

    LinkedList<int[]> list = new LinkedList<int[]>();

    list.add(x);

    System.out.println("List contains y: " + list.contains(y));

}

给出输出

    List contains y: false

这是有道理的,因为xy 是对不同内存位置的引用,但也有一种意义,它们是相等的(它们以相同的顺序具有相同的元素)。

在本例中,是否存在将true 返回到查询list.contains(y) 的数据结构?

【问题讨论】:

  • 数组没有定义合理的价值平等。这需要一个数组感知结构(非标准或),或者根据需要将数组包装在支持equals 的类中——在这种情况下,它将按预期工作,尽管工作量更大。某些数据结构(例如 HashMap)确实允许指定自定义可比较对象。
  • 正如这里的许多人所说,标准库中没有这样的内置数据结构。你想达到什么目的?您是否尝试实现isSubsetOfisSubstringOf 或其他? isSubstringOf 我的意思是确切的数组应该是原始数组的一部分。

标签: java data-structures


【解决方案1】:

我不相信有一个 Java 数据结构会像您所描述的那样为 contains() 返回 true

您可能知道,问题在于对于 Java 数组,equals() 仅测试对象身份,而不是大多数人定义的“平等”。

由于在这种情况下(并且大部分时间)contains() 依赖于 equals(),因此您会被给定的行为所困扰。

您必须实现一个专门覆盖 contains()List,以便为 Java 数组提供所需的行为,可能使用 Arrays.equals()

我的建议是使用List 而不是数组;然后你会有一个List&lt;List&lt;Integer&gt;&gt;contains() 应该在这种情况下工作,因为它将在底层 List 实现上使用 equals()

【讨论】:

    【解决方案2】:

    您需要为您的数组定义一个比较器。然后当列表查找元素时,它将使用您的比较器来查看它们是否相同:

    public static void main(String args[]) {

    int[] x = new int[] {1, 2, 3};
    int[] y = new int[] {1, 2, 3};
    
    LinkedList<int[]> list = new LinkedList<int[]>(new Comparator<int[]>() {
      @Override
      public int compare(int[] a1, int[] a2) {
        if(a1 == a2) return 0;
        if(a1 == null && a2 != null) return -1;
        if(a1 != null && a2 == null) return 1;
        if(a1.size() < a2.size()) return -1;
        if(a1.size() > a2.size()) return 1;
        for(int i = 0; i < a1.size(); i++) {
          int comp = a1[i] - a2[i];
          if(comp < 0) return -1;
          if(comp > 0) return 1;
        }
        return 0;
      }
    });
    
    list.add(x);
    
    System.out.println("List contains y: " + list.contains(y));
    

    }

    【讨论】:

    • LinkedList 不允许在其构造函数中使用自定义比较器
    • @Bengt is right。此外,这样的比较器还能做什么?
    • 天啊,我在考虑 TreeSet 或 ArrayList。你是对的。我一定一直在考虑 Set 或 ArrayList。是的,彼得的答案是使用列表列表而不是数组列表的正确方法。
    【解决方案3】:

    看起来您确实在寻找 Set 实现。

    不包含重复元素的集合。更正式地说,集合不包含一对元素 e1e2,例如 e1.equals(e2),最多包含一个 null 元素。正如暗示的那样 顾名思义,这个接口模拟了数学集合抽象。

    如果你想存储 int 值的集合,你可以使用 this Tuple class 我刚才为 another question on SO 写的。

    Set<Tuple> myTuples = new HashSet<Tuple>();
    Tuple<Integer> x = Tuple.create(1, 2, 3);
    Tuple<Integer> y = Tuple.create(1, 2, 3);
    
    myTuples.add(x);
    System.out.println("Set contains y: " + myTuples.contains(y)); // prints true
    

    如果订单很重要,您可以使用SortedSet

    【讨论】:

      【解决方案4】:

      LinkedList 使用equals 来实现contains,所以应该可以:

      public static void main(String args[]) {
          static class Ints {
              int[] array;
              public Ints(int[] array) {
                  this.array = array;
              }
              public boolean equals(Object other) {
                  if (other instanceof Ints) {
                      return arraysEqual((Ints) other);
                  }
              }
              public boolean arraysEqual(Ints other) {
                  // check that this.array and other.array are same length and
                  // have same values. Do a null check somewhere too. :)
              }
          }
      
          Ints x = new Ints(new int[] {1, 2, 3});
          Ints y = new Ints(new int[] {1, 2, 3});
      
          LinkedList<Ints> list = new LinkedList<int[]>();
      
          list.add(x);
      
          System.out.println("List contains y: " + list.contains(y));
      
      }
      

      【讨论】:

        【解决方案5】:

        如果您需要标准检查之外的任何内容,您可能希望将 LinkedList 扩展到您自己的自定义数据结构并定义自定义相等方法。

        【讨论】:

        • 这是个糟糕的建议。它正在解决错误的问题。问题是数组,而不是列表。 Peter 是对的:使用 Lists of Lists,而不是 Lists of Arrays。
        • 我承认,使用列表列表绝对是要走的路。显示我快速回答。根据 Chris 的信息,这种方式与 Peter 提到的第一种方法显然可以工作,只是不是处理此问题的优化方式。
        【解决方案6】:

        如果您可以使用 Set 而不是数组,那可能会更容易。看看herehere

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-01-10
          • 2014-09-10
          相关资源
          最近更新 更多