2

I am writing a method that creates an ArrayList S_Comp that contains all elements which are included in the array allNodes, but which are not included in the ArrayList solution (whose elements are all included in allNodes). When I print solution and allNodes, I can easily see that S_Comp should be containing 7 elements. However, all elements from allNodes are added to S_Comp, also the elements which are included in nodesS. What could be the problem here?

Below you can find my code for the method. Before calling this method, S_Comp has only been initialized as new ArrayList<MyNodesData>, so its size is 0.

public void generateSComp(DataFile testDataFile, ArrayList<Route> solution, ArrayList<MyNodesData> S_Comp)
    {
        System.out.println("solution: " + solution.toString());
        ArrayList<MyNodesData> nodesS = getNodesS(solution);
        System.out.println("NodesS: " + nodesS.toString());
        System.out.println("Size nodesS: " + nodesS.size());
        MyNodesData[] allNodes = testDataFile.getNodes();
        System.out.println("allNodes: " + Arrays.toString(allNodes));
        for(MyNodesData node : allNodes)
        {
            if(!nodesS.contains(node))
            {
                System.out.println(node.toShortString() + " is not in nodesS");
                S_Comp.add(node);
            }
        }
Mike
  • 59
  • 7
  • 5
    does MyNodesData implements hashCode and equals? – Michal Jun 05 '18 at 13:41
  • @Michal it does not, but .contains() used to work properly on MyNodesData earlier – Mike Jun 05 '18 at 13:44
  • 5
    @Mike Oh god, with our 3 names this is going to be so confusing... Without overriding equals, `contains` is using reference equality. If the objects are distinct instances with the same fields then `contains` will return false. – Michael Jun 05 '18 at 13:46
  • without overriding equals, equals method() compares references (take a look into Object.class). So as long as you work with the same objects it works. If you create new objects with same attribute values it doesn't work anymore – Michal Jun 05 '18 at 13:46
  • @Mike not without those two methods, it won't – Stultuske Jun 05 '18 at 13:46
  • @Stultuske `contains` can work fine without `equals` if you're careful about how the objects are created. For example, if all objects come from an object pool then it's not required. – Michael Jun 05 '18 at 13:48
  • @Michael it's fragile though. Like in this case it's possible that OP changed how the nodes are created somewhere else and break `contains` here. – jingx Jun 05 '18 at 13:50
  • @Michael since that's usually not the case ... and since that can't really be forced (for most datatypes) within the class ... – Stultuske Jun 05 '18 at 13:52

3 Answers3

2

Refer here for the contains method of ArrayList javadoc here: https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#contains-java.lang.Object-

It says

public boolean contains(Object o)

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

So it will work only if you override equals method of Object Class as you want in MyNodesData class. Moreover as you may already be knowing the contract between equals() and hashcode() method, it is highly recommended to override hashcode() along with equals().

For more information : Why do I need to override the equals and hashCode methods in Java?

Shubham Kadlag
  • 2,248
  • 1
  • 13
  • 32
0

contains works just as expected, it will check if the object you pass equals the object in the list. So if you are not getting the expected behavior is because those objects do not equal.

You will have to debug that code to check why the equals is not returning what you expect.

Edit: I read that you are not overriding equals and hashcode in MyNodesData class, so you should do it as other people suggest

A. Llorente
  • 1,142
  • 6
  • 16
0

override hashcode and equals method in MyNodesData class and then check.

vishal ms
  • 44
  • 3