【问题标题】:Compare new Integer Objects in ArrayList Question比较 ArrayList 问题中的新整数对象
【发布时间】:2011-02-07 16:46:00
【问题描述】:

我正在存储表示我要跟踪的对象索引的整数对象。稍后在我的代码中,我想检查特定对象的索引是否对应于我之前存储的那些整数之一。我通过创建一个 ArrayList 并从 for 循环的索引创建一个新的 Integer 来做到这一点:

ArrayList<Integer> courseselectItems = new ArrayList();

//Find the course elements that are within a courseselect element and add their indicies to the ArrayList
for(int i=0; i<numberElementsInNodeList; i++) {
    if (nodeList.item(i).getParentNode().getNodeName().equals("courseselect")) {
        courseselectItems.add(new Integer(i));
    }
}

然后我想稍后检查 ArrayList 是否包含特定索引:

//Cycle through the namedNodeMap array to find each of the course codes
for(int i=0; i<numberElementsInNodeList; i++) {
    if(!courseselectItems.contains(new Integer(i))) {
        //Do Stuff
    }
}

我的问题是,当我使用new Integer(i) 创建一个新整数时,我能否使用ArrayList.contains() 比较整数?也就是说,当我使用new Integer(i)创建一个新对象时,如果用于创建它们的int值相同,那会和之前创建的Integer对象一样吗?

我希望我没有把这说得太清楚。感谢您的帮助!

【问题讨论】:

标签: java integer arraylist


【解决方案1】:

我的问题是,当我使用 new Integer(i) 创建一个新 Integer 时,我能否使用 ArrayList.contains() 比较整数?也就是说,当我使用new Integer(i)创建一个新对象时,如果用于创建它们的int值相同,那会和之前创建的Integer对象一样吗?

简短的回答是肯定的。

长答案是......

也就是说,当我使用 new Integer(i) 创建一个新对象时,如果用于创建它们的 int 值相同,会与之前创建的 Integer 对象相同 ?

我假设您的意思是 "... 这与..." 是否是相同的instance?答案是 - 调用new 将始终创建一个与前一个实例分开的不同实例,即使构造函数参数相同。

然而,尽管有单独的身份,这两个对象会有等价的值,即在它们之间调用.equals()将返回true。

Collection.contains()

事实证明,拥有单独的等效值实例(.equals() 返回 true)是可以的。 .contains() 方法在Collection 接口中。 .contains() 的 Javadoc 描述说:

http://java.sun.com/javase/6/docs/api/java/util/Collection.html#contains(java.lang.Object)

布尔包含(对象 o)

如果此集合返回 true 包含指定的元素。更多的 正式地,当且仅当返回 true 此集合至少包含一个 元素 e 使得 (o==null ? e==null : o.equals(e)).

因此,它会做你想做的事。

数据结构

您还应该考虑您是否拥有正确的数据结构。

该列表仅与收容有关吗?顺序重要吗?你在乎重复吗?由于列表是有序的,因此使用列表可能意味着您的代码关心排序。或者您需要在数据结构中维护重复项。

但是,如果顺序不重要,如果你不想或不会有重复,如果你真的只使用这个数据结构来测试是否包含特定的值,那么你可能要考虑是否应该改用Set

【讨论】:

    【解决方案2】:

    我以(及格)测试的形式给出我的答案,作为您如何自己研究此问题的示例。并不是要阻止您使用 SO - 这很好 - 只是为了尝试推广 characterization tests

    import java.util.ArrayList;
    import junit.framework.TestCase;
    
    public class ContainsTest extends TestCase {
        public void testContains() throws Exception {
            ArrayList<Integer> list = new ArrayList<Integer>();
            assertFalse(list.contains(new Integer(17)));
            list.add(new Integer(17));
            assertTrue(list.contains(new Integer(17)));
        }
    }
    

    【讨论】:

    • 是的,现在我想起来了,我可以很容易地测试我自己。呵呵,感觉自己傻了。谢谢。 :)
    【解决方案3】:

    正如 cletus 和 DJ 所说,你的方法会奏效。

    我不知道您的代码的上下文,但如果您不关心特定索引,请考虑以下样式:

    List<Node> courseSelectNodes = new ArrayList<Node>();
    
    //Find the course elements that are within a courseselect element 
    //and add them to the ArrayList
    for(Node node : numberElementsInNodeList) {
        if (node.getParentNode().getNodeName().equals("courseselect")) {
            courseSelectNodes.add(node);
        }
    }
    
    // Do stuff with courseSelectNodes
    for(Node node : courseSelectNodes) {
        //Do Stuff
    }
    

    【讨论】:

    • 我最终改变了我的代码来做类似的事情。谢谢!
    【解决方案4】:

    是的,会发生自动装箱,但这会导致性能下降。从您的示例中不清楚为什么要以这种方式解决问题。

    另外,由于装箱,手动创建 Integer 类是多余的。

    【讨论】:

      【解决方案5】:

      是的,因为List.contains() 使用要比较的对象的equals() 方法。而Integer.equals() 会比较整数值。

      【讨论】:

        【解决方案6】:

        简短的回答是肯定的,你应该可以做ArrayList.contains(new Integer(14)),例如,看看14是否在列表中。原因是 Integer 重写了 equals 方法,以正确地将自己与具有相同值的其他实例进行比较。

        【讨论】:

          【解决方案7】:

          是的,您可以使用List.contains(),因为它使用equals(),并且在与其他Integers 进行比较时,Integer 支持这一点。

          此外,由于自动装箱,您可以简单地编写:

          List<Integer> list = new ArrayList<Integer>();
          ...
          if (list.contains(37)) { // auto-boxed to Integer
            ...
          }
          

          值得一提的是:

          List list = new ArrayList();
          list.add(new Integer(37));
          if (list.contains(new Long(37)) {
            ...
          }
          

          总是返回false,因为Integer 不是Long。这在某些时候会让大多数人绊倒。

          最后,试着让你的变量是接口类型的 Java 集合而不是具体类型:

          List<Integer> courseselectItems = new ArrayList();
          

          不是

          ArrayList<Integer> courseselectItems = new ArrayList();
          

          【讨论】:

          • 谢谢!有什么特别的原因我想让我的变量成为接口类型而不是具体类型?
          • @thechiman 具体类型是一个实现细节。 一般来说 参数、局部变量和类成员应该是接口,因此您不会被绑定到特定的实现。例如,它允许您在以后插入自定义 List 实现等。
          • 如果List 对类是完全私有的,在其他任何地方都不可见,这并不重要。但是,如果您以某种方式公开它(例如,包含列表的类有一个返回列表的方法),那么您绝对应该将其返回为List,而不是ArrayList。例如,您稍后可能会决定LinkedList 是更合适的实现。
          猜你喜欢
          • 2014-12-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-13
          • 2018-02-27
          • 2012-09-14
          相关资源
          最近更新 更多