Referencing Problem in Java (for arraylists)

I am facing a referencing problem.

I have a program that uses 2 arraylists, namely, "neighbors" And  "allNodes"

They get initialized in my program by accessing a static variable "a" of another program. For some strange reason, any modifications made to either of the two arraylists causes the same change in the other. I have checked my code thoroughly for un-intentional assignments of the nature of neighbors = allNodes, THERE ARE NONE.

MY PROGRAM:

public ArrayList neighbors = new ArrayList();
public ArrayList allNodes = new ArrayList();
LaunchContainer L = new LaunchContainer();
  ArrayList temp1 = LaunchContainer.a;
  neighbors = temp1;
   ArrayList temp2 = L.a;
   allNodes =  temp2;

Code Snippet of LaunchContainer which has the static variable "a"
-----------------------------
public class LaunchContainer {
         public static ArrayList a = new ArrayList();
        public static void main(String[] args) {
            for (int i=0;i<args.length;++i)
      {
              a.add(args[i]);
      }
      
        Container.getInstance();      
        while (true) {
            try {
                Thread.sleep(60000);              
            } catch (InterruptedException e) {
            }
        }
       
    }
------------------------

Any ideas of why this happens and HOW i may solve it ?! your help wld be appreciated :)

Regards
N


nandu2Asked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

TimYatesCommented:
If this is hapening, you have 1 of two situations

1)  You do not infact have 2 ArrayLists, you have one, and a reference to it; ie:

ArrayList a = new ArrayList() ;
ArrayList b = a ;

b.clear() ;
a.add( "Hello" ) ;

both a and b will hold the string "Hello"

2) You have two ArrayLists, but the objects inside them are references of each other...

class MyObject
{
    String val = "Hi" ;
}

ArrayList a = new ArrayList() ;
ArrayList b = new ArrayList() ;

MyObject o = new MyObject() ;
a.add( o ) ;
o.val = "Fish" ;
b.add( o ) ;

Both ArrayLists in this instance will contain a MyObject...both values of "val" will be "Fish" (as it is the same object in both lists)

0
TimYatesCommented:
You will notice that you have (1), as removing an element from one list will cause an element to vanish from the other list too

You will notice if you have (2), as changing a member variable of an oject inside one list will change the variable in the other as well...

You could of course have both (1) and (2)...

If you could post more code, we might be able to spot where you are going wrong? :-)

Tim
0
nandu2Author Commented:
So, how do I go around the problem ? Interestingly, I didn't face this problem earlier.
0
Exploring ASP.NET Core: Fundamentals

Learn to build web apps and services, IoT apps, and mobile backends by covering the fundamentals of ASP.NET Core and  exploring the core foundations for app libraries.

vk33Commented:
Look, if I'm not mistaken both temp1 and temp2 are initialized with a reference to the static ArrayList a in your LaunchContainer:

  ArrayList temp1 = LaunchContainer.a;
  neighbors = temp1;
   ArrayList temp2 = L.a;
   allNodes =  temp2;

So, both neighbors and allNodes are referencing the same ArrayList object - LaunchContainer.a. So, you have one object and two references (see TimYates suggestion).

Regards!
0
TimYatesCommented:
You have made your ArrayList static...

> public static ArrayList a = new ArrayList();

This means that ALL instances of LaunchContainer will share one ArrayList

so:

LaunchContainer L = new LaunchContainer();
  ArrayList temp1 = LaunchContainer.a;
  neighbors = temp1;
   ArrayList temp2 = L.a;
   allNodes =  temp2;

temp1 and temp2 are exactly the same ArrayList...

try doing:

LaunchContainer L = new LaunchContainer();
  ArrayList temp1 = new ArrayList( LaunchContainer.a ) ;
  neighbors = temp1;
   ArrayList temp2 = new ArrayList( L.a ) ;
   allNodes =  temp2;

This will make temp1 and temp2 NEW ArrayLists that hold the same data as LaunchContainer.a

Tim
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
TimYatesCommented:
Hehehe, too slow ;-)
0
vk33Commented:
To solve your problem I would suggest cloning arrayLists. E.g. ArrayList.clone() returns "shallow copy", you'll have separate ArrayList objects, but similar content. That's what you need, isn't it?

   ArrayList temp1 = LaunchContainer.a.clone();
   neighbors = temp1;
   ArrayList temp2 = L.a.clone();
   allNodes =  temp2;

Regards!
0
SuperKarateMonkeyCommented:
What are you actually adding to the source ArrayList, a?

And how are you modifying the element Objects?  If you're just calling some of their methods, then the underlying elements are changing, which is why both output lists are changing.
0
vk33Commented:
wow, just several seconds time difference! ;)
0
TimYatesCommented:
Hee hee :-)   Like speeding bullets we are :-)
0
nandu2Author Commented:
********** brief description of what's going on... *******
allNodes contain a list of ALL NODES OF A NETWORK
neighbors, only the neighbors of a node.

The problem arises in the line allNodes.add(msg.get(j)); of the snippet shown here. TimYates, You are right, I have case 1 and 2.
As you can see, I tried deleting the unrequired (automatic) additon that was made to neighbors arraylist, with no success.

------------
System.out.println(" LIST OF ALL NODES BEFORE ADDING NODE .. "+allNodes);
                  System.out.println(" LIST OF ALL NEIGHBRS. BEFORE ADDING NODE"+neighbors);
                  allNodes.add(msg.get(j));
                  if (neighbors.contains(msg.get(j)))
                  {
                        System.out.println("Funnily Enough, The neighbors list has the element "+ msg.get(j));


---------------

The above lines are in the following whole code..
------------------------

public void react(MessageEnvelope envelope) {
                  
                  System.out.println(" Message Received from Node "+ envelope.getSender().getName());
                  ArrayList msg = (ArrayList) envelope.getMessage();
                  System.out.println(" This is " + getHandle().getName()+ " Message received ="+ msg.toString());
                  for (int j = 0; j<msg.size(); j++){ // FOR EACH ELEMENT IN ARRAYLIST RECVD.
                        System.out.println(" ELEMENT  "+ j + " = " + msg.get(j));
      if ( !(allNodes.contains(msg.get(j))) ){
                  System.out.println(" Node is not present in my List ");
                  if (!  ((Handle.fromString("handle{"+msg.get(j)+"}")).getName()).equals(myName) )
                  {
                        // if the element is not already present in the List of all-Nodes / is not myself
                        // then add the node to the list of known nodes,
                        // ensure that your neighbors are updated about this new node too.
                  System.out.println(" Node is Not Myself, Hence adding New Node to ALL-NODES LIST " );
                  System.out.println(" LIST OF ALL NODES BEFORE ADDING NODE .. "+allNodes);
                  System.out.println(" LIST OF ALL NEIGHBRS. BEFORE ADDING NODE"+neighbors);
                  allNodes.add(msg.get(j));
                  if (neighbors.contains(msg.get(j)))
                  {
                        System.out.println("Funnily Enough, The neighbors list has the element "+ msg.get(j));
                        System.out.println("So gonna remove... ");
                        neighbors.remove(neighbors.indexOf(msg.get(j)));
                        System.out.println("Removed, Hopefully ! Let's see..");
                  }
                  System.out.println(" LIST OF ALL KNOWN NODES NOW.. " + allNodes);
                  System.out.println(" LIST OF ALL NEIGHBORS NOW ..  " + neighbors);
Integer I = new Integer(Integer.parseInt((Handle.fromString("handle{"+msg.get(j)+"}")).getName().substring(1)));
                  AllNodeID.add(I);
                  h.put(I,msg.get(j));
            }

            }
            }
            String sender = envelope.getSender().getName()+","+ envelope.getSender().getID()+",rmi://localhost:"+ envelope.getSender().getDefaultURLPort();
                                    
                  if (!(neighbors.contains(sender))){
                  System.out.println(" LIST OF ALL NEIGHBORS KNOWN BEFORE : " + neighbors);
                  
                  neighbors.add(sender);
            System.out.println(" " + envelope.getSender().getName()+ " Not Present in Neighbor's List. Adding Sender" );
                  
                  System.out.println(" LIST OF ALL NEIGHBORS KNOWN NOW... "+neighbors);
                  System.out.println(" Printing contents of All Nodes before adding... "+allNodes);
                  h.put(new Integer(Integer.parseInt(envelope.getSender().getName().substring(1))), sender);
                  Enumeration e = h.elements();
                  if (e.hasMoreElements())
                  {
                  System.out.println(" Next element " + e.nextElement());      
                  }
                  if (!(allNodes.contains(sender)))
                  {
                  
                  allNodes.add(sender);
                  System.out.println(" Adding "+ sender + " to List of All Nodes");
                  h.put(new Integer(Integer.parseInt(envelope.getSender().getName().substring(1))), sender); //hashtable for sender NUMBER - sendeR ADDRESS
                  }
                                    
                  int NodeNum = Integer.parseInt(envelope.getSender().getName().substring(1));
                  System.out.println(" Printing the Node Number that was just read ..." + NodeNum );
                  neighborID.add(new Integer(NodeNum));
                  AllNodeID.add(new Integer(Integer.parseInt(envelope.getSender().getName().substring(1))));
                  }else System.out.println(" The Sender already exists in my List of  Neighbors ");
                               
0
TimYatesCommented:
I remember once, me and cavey79 wanted the Date on here to have milliseconds....just so we could see how close we were to each other's posts ;-)

</off_topic> ;-)
0
TimYatesCommented:
Just put:

public ArrayList neighbors = new ArrayList( LocationContainer.a );
public ArrayList allNodes = new ArrayList( LocationContainer.a );

and get rid of the :

ArrayList temp1 = LaunchContainer.a;
  neighbors = temp1;
   ArrayList temp2 = L.a;
   allNodes =  temp2;

malarkey
0
SuperKarateMonkeyCommented:
To get around this, just clone your objects:


String s1 = "abc";
String s2 = "def";
a.add( s1 );
a.add( s2 );

// This is how you do it right now:

neighbors = new ArrayList( L.a );
allNodes = new ArrayList( L.a );

// This is no good.

// Try this:

for( int i = 0; i < a.size(); i++ )
{
  String temp  = (String)a.get(i);
  neighbors.add( new String( temp ) );
  allNodes.add( new String( temp ) );
}

This forces the creation of new, independent strings.  For other objects, the same principle applies, assuming you have that kind of constructor.
0
TimYatesCommented:
> This forces the creation of new, independent strings.

Why would this help?

String is immutable...it doesn't matter if you add the same one all over the shop...

Tim.
0
vk33Commented:
yes, exactly! For immutables there's no difference if you have two references or two separate objects. It's rather a "feature" than a "bug"... :)
0
B000GTCommented:
do what TimYates and vk33 suggested...
cloning is the way around this
and they have examples in their posts...
 
gl

- nc
0
nandu2Author Commented:
Thanks vk33, Yates and others ! Saved me a bunch of time :)

N
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.