I have an arraylist object catalogHierarchy of type CatalogHierarchy.
The catalogHieriarchy object has three elements. Each element has two attributes like headerName and hierarchyList. The hierarchyList element contains multiple elements of type ProductHierarchy.
I have to set a value of an attribute to Y based on headerName.
The problem I am facing is, I am making the change only for element whose headerName contains text Hierarchy. But after the iteration the catalogHierarchyFlag is set for all other two elements of cloneList object.
Could anyone please help me how to overcome this issue.
ArrayList<CatalogHierarchy> catalogHieriarchy = ... //values from database
List<CatalogHierarchy> cloneList = (ArrayList)catalogHieriarchy.clone();
for(int a=0;a<cloneList.size();a++){
if(cloneList.get(a).getHeaderName().contains("Hierarchy")){
List<ProductHierarchy> catalogHier = cloneList.get(a).getHierarchy();
for(int i = 0 ; i < catalogHier.size() ; i++) {
catalogHier.get(i).setCatalogHierarchyFlag("y");
}
}
}
Read about deep vs. shallow copies. It looks like if you compare your Objects with the == operator, it will return true, indicating that the Objects share the same reference. If you want to create an independent copy of the Object (one that does not share the same reference but that has the same values for the fields) you will have to reimplement the clone() method or provide another method. See the java docs.
Related
For those who had read my first question, I think I found where the problem is. The problem is in the mutate method and especially in this instruction:
Chromosom ch=new Chromosom(); // Chromosom is a class who use hash table
Chromosom k= new Chromosom(); // Class chromosom extends hashmap <integer,parc>
k.initialise();
for(int i=0;i<l.size();i++) ch.put(i,k.get(i)); // in this instruction i think
And this is the constructor of Chromosom:
public Chromosom(){ // construct a blank chromosom
super();
this.identifiant = 0;
NbEquipeExterne = 0;
NbEquipeInterne = 0;
CoutMinimal = 0;
CoutMensuel = 0;
}
When I change the values of ch, the values of k change too?
How can I pass the k's values to ch by copy and not by reference?
First of all Java is always pass-by-value. or rather pass-by-copy-of-the-variable-value not pass by reference. You might be changing objects of Chromosom with k in the constructor.
No danger, both ch and k are separate objects.
Furthermore you can do
ch.putAll(k);
which is a nice short-cut to remember.
Caveat
If the values of the maps are stateful objects (having mutable fields to contain some changing info), then changing that field would change the field of the simgle value object in both tables.
BitSet bits = k.get(i);
bits.set(3);
// Now ch.get(i) being the same object, also has bit 3 set.
If a class has a static field, then that field is once per class, a single instance. So you could have in say Chromosome:
static String copyright;
Chromosome.copyright = "All rights reserved"; // Clearest style
k.copyright = "All rights given to the community";
ch.copyright = "MIT license";
And you would have dealt with the same single variable, with vaklue "MIT license".
About Java
A nice design decision was made in java:
If you pass a variable to a function/method, the object/value will be passed. It may never happen that the variable itself gets an other object/value. (Not the address of the variable is passed.) Java has pass-by-value, no pass-by-reference.
I understand the idea behind a hash table, but the implementation is getting frustrating. I have done some reading and gotten mixed answers. I have read that I could implement a generic array of objects as follows:
TableContainer[] classTable =
(TableContainer<Object,Object>[]) new TableContainer[256];
where tableContainer is:
class TableContainer<key,val>{
Object key = null;
Object val = null;
}
The problem I am having is that when I try to pass the following code in a function:
classTable[i].key = x
I get a null pointer exception. I understand creating generic arrays in java gets messy because of type erasure but I thought the above implementation would work. Is there any way to create a list or array of generics to be utilized as a hashtable? (no hashtable/hashmap classes permitted)
You still have to initialize the object references inside the array before you can use them. Like so
tableContainer[] a = new tableContainer<Whatever, SomeClass>[SIZE];
for ( int i = 0 ; i < a.length; i++ ) {
a[i] = new tableContainer<Whatever, SomeClass>();
}
And of course, you must initialize the array to a size greater than 0, unlike you have in your example.
First of all you are creating an empty array:
new TableContainer[0]
and since you cannot resize arrays over time, it doesn't have much sense. Providing that you actually create an array of some positive size, you must remember one thing: you created an array of references. And by default each array is initialized to default (zero) values, which happens to be null for references.
Thus you need something like this:
classTable = new TableContainer[8];
classTable[0] = new TableContainer();
//...later
if(classTable[0] != null) { //will pass for [0], but not for [1]
classTable[0].key
}
So I'm reading this game tutorial and there is code to make arrayLists with aliens/missiles disappear upon collision.
ArrayList ms = craft.getMissiles();
for (int i = 0; i < ms.size(); i++) {
Missile m = (Missile) ms.get(i);
Rectangle r1 = m.getBounds();
for (int j = 0; j<aliens.size(); j++) {
Alien a = (Alien) aliens.get(j);
Rectangle r2 = a.getBounds();
if (r1.intersects(r2)) {
m.setVisible(false);
a.setVisible(false);
}
}
}
In the last loop, m.setVisible(false) and a.setVisible(false) make that specific alien/missile invisible but 'a' and 'm' are not part of the ArrayList they're ArrayList objects pulled out and casted into 'a' and 'm' yet the code seems to work fine given that the coder does not insert the 'a' or 'm' object back into its specific spot in the arraylist (or update its corresponding object in the arraylist).
Which makes me think, are 'a' and 'm' referenced by address to the i-th object in the arraylist as opposed to being copies?
Yes. They're references. Any time you say
A a = new A();
in Java, a is a reference, not the actual object (a common source of confusion).
When you use a standard collection, getting an element from that collection will return the reference to the contained object. Consequently it's trivial to iterate through a collection and perform changes on the contained objects.
for(int i = 0; i < list.size(); i++) {
list.get(i).clear(); // changes the object in the list...
}
Objects in Java are always copied by reference unless you clone them. Therefore, unless you're working with a primitive, it's being copied by reference, when you use the assignment operator or return it from a function.
references are copied, objects are not copied unless you call something like clone().
BTW: The ArrayList contains references. When you add a reference of an object to an ArrayList the object is not copied and it in not in the ArrayList as such.
ArrayList.get() gives you a reference to the object, not a copy.
ArrayList<yellowPage> ob1 = new ArrayList<yellowPage>();
yellowPage thing = new yellowPage(100,100);
thing.calc(i,y,s3);
ob1.add(thing);
I stored some data in thing. How can I retrieve the value stored in ob1.thing?
If you know the index, you can do yellowPage
yellowPage yp = ob1.get(index);
Otherwise you need to iterate over the list.
Iterator<yellowPate> iter = ob1.iterator();
while(iter.hasNext())
{
yellowPage yp = iter.next();
yp.whateverYouwantGet();
}
Note: I just typed code here, there may be syntax errors.
int x=5;
int info=ob1.get(x).getInfo();
The above example will get whatever information you wanted from your yellow pages class (by using a getter method) at the 6th index (because 0 counts) of your array list ob1. This example assumes you want an integer from the yellow page. You will have to create a getter method and change the x to the index of the yellow page you want to retrieve information from.
An example getter method (which you should put in your yellow pages class) could look like this:
public int getInfo() { return z; }
In the above case z may be an instance variable in your yellow pages class, containing the information you're looking for. You will most probably have to change this to suit your own situation.
If you wanted to get information from all yellow pages stored in the array list then you will need to iterate through it as Chrandra Sekhar suggested
Use an Iterator object to do this.
ArrayList<yellowPage> ob1 = new ArrayList<yellowPage>();
yellowPage thing = new yellowPage(100,100);
thing.calc(i,y,s3);
ob1.add(thing);
yelloPage retrievedThing = null;
Iterator<yelloPage> i = ob1.iterator();
if(i.hasNext()){
retrievedThing = i.next();
}
You could have the data stored in thing (horribly named variable) simply returned from the calc method. That way you don't need to maintain state for prior calculations in subsequent calls. Otherwise you just need a getter type method on the YellowPage class.
public class YellowPage {
private int result;
public void calc(...) {
result = ...
}
public int getResult() {
return result;
}
}
Print the list and override toString method.
public String toString()
{
return (""+ a+b); //Here a and b are int fields declared in class
}
System.out.print(ob1);
Class ArrayList<E>
Syntax
ArrayList<Integer> list = new ArrayList<Integer>();
You replace "Integer" with the class that the list is of.
An application can increase the capacity of an ArrayList instance before adding a large number of elements using the ensureCapacity operation. This may reduce the amount of incremental reallocation.
E represents an Element, which could be any class.
ensureCapacity is used to ensure that the list has enough capacity to take in the new elements. It's called internally every time you add a new item to the list. As the name suggests, ArrayList uses an Array to store the items. So when the array is initialized, it's given an arbitrary length, say 10. Now once you've added 10 items, if you go to add the 11th item, it'll crash because it exceeds the arrays capacity. Hence, ensureCapacity is called (internally) to ensure that there's enough space. So if you were adding the 11th element, the array size might be, say, doubled, to 20.
I was wondering, in java, is it possible to in anyway, simulate pass by reference for an array? Yes, I know the language doesn't support it, but is there anyway I can do it. Say, for example, I want to create a method that reverses the order of all the elements in an array. (I know that this code snippet isn't the best example, as there is a better algorithms to do this, but this is a good example of the type of thing I want to do for more complex problems).
Currently, I need to make a class like this:
public static void reverse(Object[] arr) {
Object[] tmpArr = new Object[arr.length];
count = arr.length - 1;
for(Object i : arr)
tmpArr[count--] = i;
// I would like to do arr = tmpArr, but that will only make the shallow
// reference tmpArr, I would like to actually change the pointer they passed in
// Not just the values in the array, so I have to do this:
for(Object i : tmpArr)
arr[count++] = i;
return;
}
Yes, I know that I could just swap the values until I get to the middle, and it would be much more efficient, but for other, more complex purposes, is there anyway that I can manipulate the actual pointer?
Again, thank you.
is there anyway that I can manipulate the actual pointer?
Java does not pass by reference, so you can't directly manipulate the original pointer. As you've found out, Java passes everything by value. You can't pass a reference to an array object, and expect a method to modify the original reference to point to another array object.
You can, of course:
Modify elements of the referred array object (ala java.util.Arrays.sort)
Pass a reference to an object with a settable field (e.g. Throwable has a setStackTrace)
return the new reference instead (ala java.util.Arrays.copyOf)
Well, you can explicitly pass an object that contains a reference. java.util.concurrent.atomic.AtomicReference is ready out of the box, although it does come with volatile semantics that you probably don't want. Some people use single element arrays to returns values from anonymous inner classes (although that doesn't seem a great idea to me).
This method reverses the Array's elements in place. The caller sees the changes. (In Java everything is passed by value, including object references.)
public static void reverse(Object[] arr) {
for ( int i = 0, j = arr.length - 1; i < j; i++, j-- ) {
Object temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
In Java Object reference is passed by value.
So if you looking for something like
function referenceCheck()
{
int[] array = new int[]{10, 20, 30};
reassignArray(&array);
//Now array should contain 1,2,3,4,5
}
function reassignArray(int **array)
{
int *array = new int[] { 1, 2, 3, 4, 5};
}
Then its not possible in Java by any direct means.
If we need to change only the values stored in an array, then we can do it since object reference is passed by value.
You want to pass a reference to the array reference. In that case you just have to either create a class to hold the reference and pass a reference to that class or just pass a 1-element array of the type being passed. Then you'd be passing either an object holding the array or an array whose only element contains the array you want to operate on.