views:

301

answers:

7

I am storing Integer objects representing an index of objects I want to track. Later in my code I want to check to see if a particular object's index corresponds to one of those Integers I stored earlier. I am doing this by creating an ArrayList and creating a new Integer from the index of a for loop:

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));
    }
}

I then want to check later if the ArrayList contains a particular index:

//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
    }
}

My question is, when I create a new Integer by using new Integer(i) will I be able to compare integers using ArrayList.contains()? That is to say, when I create a new object using new Integer(i), will that be the same as the previously created Integer object if the int value used to create them are the same?

I hope I didn't make this too unclear. Thanks for the help!

+3  A: 

Yes, you can use List.contains() as that uses equals() and an Integer supports that when comparing to other Integers.

Also, because of auto-boxing you can simply write:

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

It's worth mentioning that:

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

will always return false because an Integer is not a Long. This trips up most people at some point.

Lastly, try and make your variables that are Java Collections of the interface type not the concrete type so:

List<Integer> courseselectItems = new ArrayList();

not

ArrayList<Integer> courseselectItems = new ArrayList();
cletus
Thanks! Is there any particular reason I want to make my variables of the interface type and not the concrete type?
thechiman
@thechiman the concrete type is an implementation detail. *Generally speaking* parameters, local variables and class members should be the interface so you're not tied to a particular implementation. It allows you to, for example, plugin a custom `List` implementation at some later point, etc.
cletus
@cletus This isn't so important if the `List` is completely private to the class, visible nowhere else. But if you are exposing it in some way (for example, the class containing the list has a method to return the list), then you should definitely return it as a `List` and not as an `ArrayList`. You might decide later, for example, that `LinkedList` is a more appropriate implementation.
isme
+1  A: 

Short answer is yes, you should be able to do ArrayList.contains(new Integer(14)), for example, to see if 14 is in the list. The reason is that Integer overrides the equals method to compare itself correctly against other instances with the same value.

Sean
+1  A: 

Yes it will, because List.contains() use the equals() method of the object to be compared. And Integer.equals() does compare the integer value.

DJ
A: 

Yes, automatic boxing occurs but this results in a performance penalty. Its not clear from your example why you would want to solve the problem in this manner.

Also, because of boxing, creating the Integer class by hand is superfluous.

nick
+1  A: 

As cletus and DJ mentioned, your approach will work.

I don't know the context of your code, but if you don't care about the particular indices, consider the following style also:

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
}
binil
I like this too. I might change my code to do this. Thanks!
thechiman
I ended up changing my code to do something similar to this. Thanks!
thechiman
+1  A: 

I'm putting my answer in the form of a (passing) test, as an example of how you might research this yourself. Not to discourage you from using SO - it's great - just to try to promote 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)));
    }
}
Carl Manaster
Yeah, now that I think about it, I could have easily tested this my self. Heh, I feel dumb. Thanks. :)
thechiman
+1  A: 

The short answer is yes.

The long answer is ...

...will that be the same as ...?

That is to say, when I create a new object using new Integer(i), will that be the same as the previously created Integer object if the int value used to create them are the same?

I assume you mean "... will that be the same instance as ..."? The answer to that is no - calling new will always create a distinct instance separate from the previous instance, even if the constructor parameters are identical.

However, despite having separate identity, these two objects will have equivalent value, i.e. calling .equals() between them will return true.

Collection.contains()

It turns out that having separate instances of equivalent value (.equals() returns true) is okay. The .contains() method is in the Collection interface. The Javadoc description for .contains() says:

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

boolean contains(Object o)

Returns true if this collection contains the specified element. More formally, returns true if and only if this collection contains at least one element e such that (o==null ? e==null : o.equals(e)).

Thus, it will do what you want.

Data Structure

You should also consider whether you have the right data structure.

Is the list solely about containment? is the order important? Do you care about duplicates? Since a list is order, using a list can imply that your code cares about ordering. Or that you need to maintain duplicates in the data structure.

However, if order is not important, if you don't want or won't have duplicates, and if you really only use this data structure to test whether contains a specific value, then you might want to consider whether you should be using a Set instead.

Bert F