skiwi
skiwi

Reputation: 69259

Java arraylist copy - clone?

I am trying to copy an ArrayList, but it seems to be just referencing it and not really copying it.

My code:

List<Column> columns = columnData(referencedField.table);
List<Field> newPath = new ArrayList<>(startPath);
System.out.println("Equals? " + (newPath.equals(startPath)));

startPath is an ArrayList<Field> being passed into the function.

Field:

public class Field 
{
    public String table;
    public String column;

    public Field(final String table, final String column) {
        this.table = table;
        this.column = column;
    }

    @Override
    public String toString() {
        return "(" + table + ", " + column + ")";
    }

    @Override
    public int hashCode() {
        int hash = 3;
        hash = 67 * hash + Objects.hashCode(this.table);
        hash = 67 * hash + Objects.hashCode(this.column);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Field other = (Field) obj;
        if (!Objects.equals(this.table, other.table)) {
            return false;
        }
        if (!Objects.equals(this.column, other.column)) {
            return false;
        }
        return true;
    }
}

Now I have read about cloning it, but I am not experienced in it. I am actually wondering if a clone will really create a list of new objects such that they are not being equal anymore, as with same contents the elements would be equal.

So to rephrase, what I want is: To make sure that startPath and newPath are not equal and thus not referenced to eachother, as I am using the Lists a recursive function that should add the lists to a map.

Upvotes: 1

Views: 1053

Answers (2)

Thihara
Thihara

Reputation: 6969

If you are using the overridden equals methods in your classes instead of the referential equality, the copied collection will be equal to the original :-).

There's no way to make this not the case if you have properly overridden the equals methods. No matter how you clone or copy it they will still be the same..

Let me elaborate.

List<Field> newPath = new ArrayList<>(startPath);

will copy the content of startPath quite well. It calls a native function to copy the internal array so rest assured you objects are deep copied.

The problem is in the way ArrayList's equals method works. Well it's not a problem, it's the proper way to do it, but it's the reason you are not getting the in equality in this particular instance.

When you call

newPath.equals(startPath)

it will iterate over the elements and compare all of them using their equals method. If the element type's equals method is overridden to consider it's state instead of the default referential equality (as is the case with your Field class) then all the elements in both the lists are equal.

Because their data is equal even though they are not the same objects.

Upvotes: 1

Kevin Bowersox
Kevin Bowersox

Reputation: 94429

You need to make a deep copy.

List<Field> newPath = new ArrayList<>();
for(Field field: startPath){
   newPath.add(field.clone());
}

Upvotes: 3

Related Questions