【问题标题】:Java ArrayList: contains() method returns false when arraylist contains the given objectJava ArrayList:当arraylist包含给定对象时,contains()方法返回false
【发布时间】:2012-11-01 21:23:08
【问题描述】:

我遇到了 contains() 方法的问题,即使 ArrayList 包含给定的 Object,它也会返回 false。 我的代码如下:

String [] transaction = dbConnection.getPendingTransaction(username);
if (!onlineConnection.getSentTransactionRequests().contains(transaction)) {
    onlineConnection.getSentTransactionRequests().add(transaction);

    String packet = "RTR" + "_" + transaction[0] + "_" + transaction[2] + 
                        "_" + transaction[3] + "_" + transaction[4];
    onlineConnection.send(packet);
}

我在两次迭代之间尝试了Thread.sleep(),所以ArrayList 没有成功加载。

【问题讨论】:

  • equalshashcode 显然不是你的朋友。
  • 拜托,拜托,请将您的交易建模为适当的对象,而不是字符串数组。然后看上面@haylem 的评论。

标签: java arrays arraylist contains evaluation


【解决方案1】:

数组的hashCode()equals() 在涉及到这一点时有点坏(这是一个很长的不同讨论原因)。

一种可能的解决方法是使用ArrayList<ArrayList<String>> 而不是ArrayList<String[]>ArrayListequals() 方法将如您所愿。

例如:

    ArrayList<String> l1 = new ArrayList<>();
    ArrayList<String> l2 = new ArrayList<>();
    l1.add("asdf");
    l2.add("asdf");
    ArrayList<ArrayList<String>> coll = new ArrayList<>();
    coll.add(l1);
    System.out.println(coll.contains(l2));

将产生true,正如预期的那样

【讨论】:

  • 如果这确实是问题所在,那么“长期不同的讨论为什么”将是值得的。
  • @DonRoby:老实说,我相信在 java 7 中仍然是这种方式的主要原因是向后兼容。我相信,如果设计人员可以在不改变 java 的向后兼容性准则的情况下改变它——他们会……但我不是 Oracle 的架构师,所以我可能是错的。我也认为这是题外话。
  • 确实是这个问题,原因在stackoverflow.com/questions/8777257/…的相关问题中。
【解决方案2】:

查看 getPendingTransaction 和 getSentTransactionRequests 是否应该返回相同的数组而不是创建新的数组。其次,尝试调试并查找数组对象 ID。如果这不一样,但应该是(并且包含相同的元素),请尝试解决此问题(例如创建比较器或列表或类似的东西)。

【讨论】:

    【解决方案3】:

    问题是数组的equals 被定义为引用相等。换句话说,包含相同元素的两个不同数组不相等...根据equals 方法。

    如果您希望“事务”对象的equals 基于字符串的相等性,则需要创建一个自定义类来保存String[],并覆盖equals 方法和@987654326 @方法。


    顺便说一句,数组equals(Object) 方法不是“有点坏”。 equals 定义的语义只是反映了任何数组对象本质上都是可变的这一事实。

    【讨论】:

      【解决方案4】:

      这是因为String [] transaction 是对象。当您调用contains 时,列表使用equals 方法将新对象与其他对象进行比较。想象它喜欢做

      new Object().equals(new Object())
      

      【讨论】:

      • 不完全正确,请注意,如果集合包含“asdf”并且您检查list.contains(new String("asdf")),您将得到正确的结果。
      • @amit 谢谢。更新了我的答案。
      【解决方案5】:

      如果你必须使用List&lt;String[]&gt;,可能你使用equals()hashCode()似乎运气不好......

      也许你最好创建方法来比较你的对象

      类似

      public static boolean stringArrayListEquals(List<String[]> list, List<String[]> list2) {
          if (list.size() != list2.size()) return false;
          for (int i = 0; i < list.size(); ++i){
              if (!Arrays.equals(list.get(i), list2.get(i)) return false;
          }
          return true;
      }
      

      要测试contains(),您需要另一个循环...

      虽然你应该认真地改用List&lt;List&lt;String&gt;&gt;

      【讨论】:

        【解决方案6】:

        我也遇到过类似的问题。我刚刚写了下面的sn-p:

        assertContains(list, toLookFor);  // To call the below private method  
        
        private void assertContains(ArrayList<String> list, String toLookFor) {
                String arrayListToString = rulesList.toString();
                
                 if (arrayListToString.contains(toLookFor))
                        System.out.println("The list contains "+ toLookFor);
                    else
                        System.out.println("The list does not contains "+ toLookFor);
                
            }
        

        【讨论】:

          猜你喜欢
          • 2019-02-18
          • 2021-01-28
          • 2013-11-28
          • 1970-01-01
          • 2014-08-20
          • 1970-01-01
          • 2015-05-02
          • 2013-04-22
          • 2015-10-27
          相关资源
          最近更新 更多