I have the following code (this is just an example that I thought of for the concept I am having trouble with)

String fileName = "example3.txt";
		Reader reader = new Reader();
		ArrayList<String> vertices = reader.getVertices(fileName);
		Matrix m = new Matrix(vertices);
		Matrix m2 = m;
		m.setEdges(fileName);
		
		m2.print();
		m.print();

what I want is m2 to be what m was before m gets changed because of the setEdges. But when I print both m and m2 they seem the same:

vertices are: [A, B, C, D, E, F, G, H, I]
matrix [[*, A, B, C, D, E, F, G, H, I], [A, 0, 1, 0, 0, 0, 0, 0, 0, 0], [B, 1, 0, 1, 0, 0, 0, 0, 0, 0], [C, 0, 1, 0, 1, 1, 1, 1, 0, 0], [D, 0, 0, 1, 0, 1, 0, 0, 0, 0], [E, 0, 0, 1, 1, 0, 1, 1, 0, 0], [F, 0, 0, 1, 0, 1, 0, 1, 0, 0], [G, 0, 0, 1, 0, 1, 1, 0, 0, 0], [H, 0, 0, 0, 0, 0, 0, 0, 0, 0], [I, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
matrix [[*, A, B, C, D, E, F, G, H, I], [A, 0, 1, 0, 0, 0, 0, 0, 0, 0], [B, 1, 0, 1, 0, 0, 0, 0, 0, 0], [C, 0, 1, 0, 1, 1, 1, 1, 0, 0], [D, 0, 0, 1, 0, 1, 0, 0, 0, 0], [E, 0, 0, 1, 1, 0, 1, 1, 0, 0], [F, 0, 0, 1, 0, 1, 0, 1, 0, 0], [G, 0, 0, 1, 0, 1, 1, 0, 0, 0], [H, 0, 0, 0, 0, 0, 0, 0, 0, 0], [I, 0, 0, 0, 0, 0, 0, 0, 0, 0]]


Why? I said m2=m before m was changed and yet m2 is taking the change into account. What should be happening is that m2 should be :
matrix [[*, A, B, C, D, E, F, G, H, I], [A, 0, 0, 0, 0, 0, 0, 0, 0, 0], [B, 0, 0, 0, 0, 0, 0, 0, 0, 0], [C, 0, 0, 0, 0, 0, 0, 0, 0, 0], [D, 0, 0, 0, 0, 0, 0, 0, 0, 0], [E, 0, 0, 0, 0, 0, 0, 0, 0, 0], [F, 0, 0, 0, 0, 0, 0, 0, 0, 0], [G, 0, 0, 0, 0, 0, 0, 0, 0, 0], [H, 0, 0, 0, 0, 0, 0, 0, 0, 0], [I, 0, 0, 0, 0, 0, 0, 0, 0, 0]]


can someone explain what is going on and how I can get the new object that I want a copy of to not take into account the changes made to the object it is a copy of? Is the clone method involved? But I don't have a .clone() appearing when I go m. so what should I do?

Thanks

Recommended Answers

All 6 Replies

You're correct that you need to create a copy of that object before you alter it. Using '=' is setting the two variables to be references to the exact same object in memory, hence it reflects the changes. If your Matrix class doesn't implement the clone method then you will have to take whatever steps are necessary to create a copy yourself.

FYI, to add to what Ezzaral said, the clone method makes a shallow copy, not a deep copy. So it will just be a reference to the same object, not a new copy of the object. If you want to make a new copy of an Object, which is NOT the same reference, override the clone method or make your own method.

override the clone method as such; this should be done in your Matrix class

List<String> newVertices = new ArrayList<String>();
Collections.copy(newVertices, this.vertices); // import java.util.Collections

return new Matrix(newVertices);

this should do the trick

hello all, thanks for your suggestions.

ejosiah - I tried it your way but seem to get some sort of exception that says the size isn't right/source couldn't fit in destination etc.

But I have tried a cloning method:

Here is my Matrix class:

public class Matrix implements Cloneable{
	
	private ArrayList<ArrayList<String>> graph;
	private ArrayList<String> vertexCover;
	private ArrayList<String> theVertices;
	private int parameterK;
	

	@SuppressWarnings("unchecked")
	public Object clone(){
		try{
	
			Matrix cloned = (Matrix) super.clone();
			cloned.graph =  (ArrayList<ArrayList<String>>) graph.clone(); 
			cloned.theVertices = (ArrayList<String>) theVertices.clone();
			cloned.vertexCover = (ArrayList<String>) vertexCover.clone();
			return cloned;
		}
		catch(CloneNotSupportedException e){
			return null;
		}
	}
	
	/**
	 * set up the Matrix with vertices and a field to keep track of vertex cover
	 * and parameterK????
	 * Matrix row & column labels are added and matrix initialised with 0s
	 * @param vertices
	 */
	public Matrix(ArrayList<String> vertices, int parameter){
		
		vertices.add(0, "*"); //to offset for the row names put * in index 0
		parameterK = parameter; 
		vertexCover = new ArrayList<String>();
		//to access vertices easily
		theVertices = vertices;
		
		//create the matrix & add the column names
		graph = new ArrayList<ArrayList<String>>();
		graph.add(vertices); 
		System.out.println("inconst");
		 //insert all the subsequent rows
		for(int i=1;i<vertices.size();i++){
			ArrayList<String> row = new ArrayList<String>(); //create the rows
			row.add(vertices.get(i)); //set the first element to vertex name
			for(int j=1;j<vertices.size();j++){ //populate the rows with elements
				row.add("0"); //initialize the matrix to 0s
			}		
			graph.add(row); //add the row
		}
	}

But I am still having some issues.
My remove method has been tested and I know it works fine normally:

public void removeVertex(String vertex){
		System.out.println("---------------START REMOVE");
		//get the index value of the vertex to be removed
		int i = getGraph().get(0).indexOf(vertex);
		
		//remove the vertex row 
		System.out.println("remove "+i+"th row "+vertex);
		getGraph().remove(i); //remove the ith row
		print();
		
		System.out.println("remove clmns");
		//remove the column
		for(int index =0;index<graph.size();index++){ //iterate through each remaining row
			System.out.println("remove "+i+" from "+index+"th clmn from"+graph.get(index));
			getGraph().get(index).remove(i); //remove the element at position i = vertex 
			print();
		}
		//remove vertex from field in Matrix
		theVertices.remove(vertex);
		System.out.println("the vertices: "+theVertices);
		System.out.println("---------------END REMOVE");
	}

BUT when I create copies/clones I am having issues still.

In my unit test I try -

@Before
	public void setUp(){
		//instantiate the graph object
		ArrayList<String> vertices = new ArrayList<String>();
		vertices.add("a"); vertices.add("b"); vertices.add("c");
		int parameter = 5;
		
		graph = new Matrix(vertices, parameter);
				
	}


@Test
	public void testRemoveVertex() {
		graph.addEdge("a", "b");
		Matrix m2 = (Matrix) graph.clone();
		System.out.println("this is m2 ");m2.print();
		
		assertTrue(graph.isEdge("a", "b")); //there is an edge between a and b
		graph.removeVertex("a");
		assertFalse(graph.isEdge("a", "b")); //the edge should be gone
		assertFalse(graph.isEdge("b", "a")); //the edge should be gone
		assertFalse(graph.getTheVertices().contains("a")); //the matrix's theVertices field should be reduced
		
		System.out.println("this is graph ");graph.print();
		System.out.println("this is graph "+graph.getTheVertices());
		
		System.out.println("this is m2 ");m2.print();
		System.out.println("this is m2 "+m2.getTheVertices());
	}

My output:

inconst
this is m2 
matrix [[*, a, b, c], [a, 0, 1, 0], [b, 1, 0, 0], [c, 0, 0, 0]]
---------------START REMOVE
remove 1th row a
matrix [[*, a, b, c], [b, 1, 0, 0], [c, 0, 0, 0]]
remove clmns
remove 1 from 0th clmn from[*, a, b, c]
matrix [[*, b, c], [b, 1, 0, 0], [c, 0, 0, 0]]
remove 1 from 1th clmn from[b, 1, 0, 0]
matrix [[*, b, c], [b, 0, 0], [c, 0, 0, 0]]
remove 1 from 2th clmn from[c, 0, 0, 0]
matrix [[*, b, c], [b, 0, 0], [c, 0, 0]]
the vertices: [*, b, c]
---------------END REMOVE
this is graph 
matrix [[*, b, c], [b, 0, 0], [c, 0, 0]]
this is graph vertices [*, b, c]
this is m2 
matrix [[*, b, c], [a, 0, 1, 0], [b, 0, 0], [c, 0, 0]]
this is m2 vertices [*, a, b, c]

This output tells me that my cloning method HALF works but can't figure out why what doesn't work isn't working. So
m2 should actually be:
[[*, a, b, c], [a, 0, 1, 0], [b, 1, 0, 0], [c, 0, 0, 0]]
but it ends up:
matrix [[*, b, c], [a, 0, 1, 0], [b, 0, 0], [c, 0, 0]]
It is leaving a row alone (it relates to this line in removeVertex: getGraph().remove(i); ) But it is not leaving the 'a' column's values alone. I...am not sure where the issue is or how I can even resolve it?

* a b c
a 0 1 0
b 1 0 0
c 0 0 0

Could someone please let me know if I am making a huge error somewhere? I have read so many sites on cloning and I am sure I am employing deep cloning so why it won't work is really frustuating!!!

Thanks

ETA: should I make a seperate post for this? Because the issue is no longer "=" but rather cloning? Let me know if I should and I will do so.

You're correct that you need to create a copy of that object before you alter it. Using '=' is setting the two variables to be references to the exact same object in memory, hence it reflects the changes

Yeah i got tripped up by that recently. I was using == to compare values, when what it does is compare two objects to determine if they are the same object in memory.

P.S its a logical continuation, so not really any need for a new post.

Issue solved -
the problem was that the ArrayLists inside the ArrayLists weren't getting cloned.

For anyone else who has the same trouble here is my cloning method that I changed:

public Matrix clone(){
		try{
			Matrix cloned = (Matrix) super.clone();
			cloned.graph = new ArrayList<ArrayList<String>>();
			for (int i=0; i<graph.size(); i++){
				ArrayList<String> row = (ArrayList<String>) graph.get(i).clone();
				cloned.graph.add(i, row);
			}
			cloned.theVertices = (ArrayList<String>) theVertices.clone();
			cloned.vertexCover = (ArrayList<String>) vertexCover.clone();
			return cloned;
		}
		catch(CloneNotSupportedException e){
			return null;
		}
	}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.