Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / November 2007

Tip: Looking for answers? Try searching our database.

Newbie Question - ArrayLists and methods

Thread view: 
Taria - 11 Nov 2007 10:46 GMT
Hello all (again),

My problem here is that I'm trying to build a list of ArrayLists that
hold data and I want to add the newly derived data into a table where
it's dependent on the first row.  A short version of my program to
illustrate what I mean:

import java.util.*;
  public class MyProg2 {
     public static void main(String[] args) {
        List table  = new ArrayList ();
        List <Integer> data = new ArrayList <Integer>();
        data.add(1);
        data.add(3);
        data.add(4);
        table.add(data);

        System.out.println ("table(0) = " + table.get(0));

        ArrayList <Integer> newNode = new ArrayList <Integer>();
        newNode = createNode((ArrayList)table.get(0),0);
        table.add(newNode);
        System.out.println ("Added in a new row and table is now:");
        System.out.println ("table(0) = " + table.get(0));
        System.out.println ("table(1) = " + table.get(1));

      }  //end main driver
      public static ArrayList createNode(ArrayList items,int lParen){
         int a = 0; int b=0; int c=0;
         if (items.size() >= 2){
           a = Integer.valueOf(items.get(lParen).toString());
           b = Integer.valueOf(items.get(rParen).toString());
           c = a + b;
           items.remove(lParen);
           items.remove(lParen);
           items.add(lParen,c);
        }
        return items;
     }
}

(I'm unable to get rid of all the unchecked msgs because putting the
<Integer> tag sometimes made the program uncompilable.  Use --nowarn
when you compile this program.  :)

Iin this code, row 0 of table is changed in the method while it
creates row 1, but I don't understand why and don't know how to keep
it from changing.   From this behavior, it's leading me to believe
ArrayLists are passed by value or is this the way of ArrayLists?  I
thought parameters were passed by reference?  What am I missing here?

-t
Joshua Cranmer - 11 Nov 2007 14:25 GMT
> Hello all (again),
>
[quoted text clipped - 7 lines]
>       public static void main(String[] args) {
>          List table  = new ArrayList ();

List<List<Integer>> table = new ArrayList<List<Integer>>();

>          List <Integer> data = new ArrayList <Integer>();
>          data.add(1);
[quoted text clipped - 6 lines]
>          ArrayList <Integer> newNode = new ArrayList <Integer>();
>          newNode = createNode((ArrayList)table.get(0),0);

... so you can change this line to:
newNode = createNode(table.get(0),0);

>          table.add(newNode);
>          System.out.println ("Added in a new row and table is now:");
[quoted text clipped - 3 lines]
>        }  //end main driver
>        public static ArrayList createNode(ArrayList items,int lParen){

public static List<Integer> createNode(List<Integer> items, int lParen){

>           int a = 0; int b=0; int c=0;
>           if (items.size() >= 2){
>             a = Integer.valueOf(items.get(lParen).toString());
>             b = Integer.valueOf(items.get(rParen).toString());

typo? I see no `rParen' defined anywhere.

>             c = a + b;
>             items.remove(lParen);
[quoted text clipped - 4 lines]
>       }
> }

Here is my rough estimate of what the second method should look like:
public static List<Integer> createNode(List<Integer> items,
        int leftIndex, int rightIndex) {
    // Create a copy so we can modify without changing...
    items = new ArrayList<Integer>(items);
    if (items.size() >= 2){
        int sum = items.get(leftIndex)+items.get(rightIndex);
        // Remove from the right first -- otherwise we're off by one.
        items.remove(rightIndex);
        items.remove(leftIndex);
        items.add(leftIndex,sum);
    }
    return items;
}

> (I'm unable to get rid of all the unchecked msgs because putting the
> <Integer> tag sometimes made the program uncompilable.  Use --nowarn
> when you compile this program.  :)

Have you read up on generics?

> Iin this code, row 0 of table is changed in the method while it
> creates row 1, but I don't understand why and don't know how to keep
> it from changing.   From this behavior, it's leading me to believe
> ArrayLists are passed by value or is this the way of ArrayLists?  I
> thought parameters were passed by reference?  What am I missing here?

Row 0 is changing because the parameters are being passed by reference.
You send in the list of items, and it simultaneously affects both the
to-be-returned value and the input (rows 1 and 0, respectively). To keep
it from changing, you want to create a copy of the row, which is what
the first line of my method does.

Signature

Beware of bugs in the above code; I have only proved it correct, not
tried it. -- Donald E. Knuth

Lew - 11 Nov 2007 16:17 GMT
> Row 0 is changing because the parameters are being passed by reference.

According to Sun and the language lawyers, the parameters are passed by value.
 The values happen to be references.

> You send in the list of items, and it simultaneously affects both the
> to-be-returned value and the input (rows 1 and 0, respectively). To keep
> it from changing, you want to create a copy of the row, which is what
> the first line of my method does.

As did the code I posted to the first version of this question.

> public class Matriculate
> {
[quoted text clipped - 42 lines]
>  }
> }

Signature

Lew

Taria - 11 Nov 2007 17:22 GMT
Looking back, I see it now.  To be honest, Lew, your code intimidated
me because of all the new statements it (new to me anyway.)  There are
quite a few new keywords I liked that I want to try using once I get
the basic structure down for my program.  Your code is one of those
things that I have to read multiple times on different days to
understand like Cormen's book.

Thanks to Daniel, Donald and Lew, I now understand how to manipulate
an ArrayList within a block and method.  I think I can finish this
homework project that I have to do with the concepts I have learned in
the last few days.  I'm about 15% done.

Personally, I think it's odd that you have to make a copy of a passed
parameter before using it to avoid modifying it within a method.  I
thought that the parameters retained their value (if passed by
reference) despite modification during the course of the method
activation.  I'm going to have to try experimenting with this part
after I'm done with this program!  :)

-t (the grateful Newbie Java programmer)
Daniel Pitts - 11 Nov 2007 22:00 GMT
> Personally, I think it's odd that you have to make a copy of a passed
> parameter before using it to avoid modifying it within a method.  I
[quoted text clipped - 4 lines]
>
> -t (the grateful Newbie Java programmer)

Actually, the way it works, is when you use "new Something", it
allocates the room for the Something object, and does all its
initialization "magic".

After that, you have exactly one Something, and anything that references
it references the exact same Something object.  The references
themselves are copied, but the object they reference isn't copied or moved.

In other words, the semantics of Java parameters are that primitives and
references are passed-by-value, but objects are only accessible through
a reference, so the objects are never passed-by-value.

Hope this clarifies things.

Signature

Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>

Roedy Green - 11 Nov 2007 23:12 GMT
On Sun, 11 Nov 2007 14:00:41 -0800, Daniel Pitts
<newsgroup.spamfilter@virtualinfinity.net> wrote, quoted or indirectly
quoted someone who said :

>In other words, the semantics of Java parameters are that primitives and
>references are passed-by-value, but objects are only accessible through
>a reference, so the objects are never passed-by-value.

see http://mindprod.com/jgloss/callbyreference.html
http://mindprod.com/jgloss/callbyvalue.html
Signature

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com

Roedy Green - 11 Nov 2007 23:10 GMT
>Personally, I think it's odd that you have to make a copy of a passed
>parameter before using it to avoid modifying it within a method.  I
>thought that the parameters retained their value (if passed by
>reference) despite modification during the course of the method
>activation.

You don't quite get it yet.  Let me try yet another explanation.

When you call a method, a COPY of the value of the argument is passed
to the stack to become the local parameter inside the method.  If you
modify it in the method, it won't charge any variables in the caller,
but it will change the value of your local variable.

If you use the word "final" on your parameter, if you try to modify
the value, the compiler won't let you.

If you need both the original value of the argument and a modified
value, you will need two variables, one to hold the old and one to
hold the new value.  However, even in that case the caller's variables
will be untouched.

See http://mindprod.com/jgloss/parameter.html
http://mindprod.com/jgloss/argument.html
Signature

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com

Curt Welch - 12 Nov 2007 00:10 GMT
> >Personally, I think it's odd that you have to make a copy of a passed
> >parameter before using it to avoid modifying it within a method.  I
> >thought that the parameters retained their value (if passed by
> >reference) despite modification during the course of the method
> >activation.

[snip]

> If you need both the original value of the argument and a modified
> value, you will need two variables, one to hold the old and one to
> hold the new value.  However, even in that case the caller's variables
> will be untouched.

I generally try to not modify pass by value parameters as a matter of
style.  I don't always follow my own rules but most the time, if I need to
modify it, I will normally create a new local variable and only modify the
local variable.  I find that it's very common that you will need the
original value at some point in the future and it's also common to not
always notice that the argument was modified locally.  It's a nasty way for
obscure bugs to creep into the code when the argument is only modified on
certain rare conditions so the code added later that assumes it is working
with the original value only breaks on the rare conditions.

I find it's best to logically think of arguments as final (aka read only).
Logically, it's better to treat the parameter as belonging to the calling
code and not belonging to the local code even though pass by value
arguments are technically local.  I think it helps you keep the correct
mindset when you deal with the parameters that aren't passed by value (the
contents of all objects and arrays).

> See http://mindprod.com/jgloss/parameter.html
> http://mindprod.com/jgloss/argument.html

Signature

Curt Welch                                            http://CurtWelch.Com/
curt@kcwc.com                                        http://NewsReader.Com/

Roedy Green - 12 Nov 2007 00:24 GMT
>I find it's best to logically think of arguments as final (aka read only).
>Logically, it's better to treat the parameter as belonging to the calling
>code and not belonging to the local code even though pass by value
>arguments are technically local.

I have got into the habit of marking everything final, then removing
the final if I have to.  It is amazing when you do that how few
non-final variables there are.  I almost wish variables were final by
default and you had to declare them "mutable".
Signature

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com

Daniel Pitts - 12 Nov 2007 00:29 GMT
>> I find it's best to logically think of arguments as final (aka read only).
>> Logically, it's better to treat the parameter as belonging to the calling
[quoted text clipped - 5 lines]
> non-final variables there are.  I almost wish variables were final by
> default and you had to declare them "mutable".
True that.

Signature

Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>

Chris ( Val ) - 12 Nov 2007 05:30 GMT
On Nov 12, 11:24 am, Roedy Green <see_webs...@mindprod.com.invalid>
wrote:

> >I find it's best to logically think of arguments as final (aka read only).
> >Logically, it's better to treat the parameter as belonging to the calling
[quoted text clipped - 3 lines]
> I have got into the habit of marking everything final, then removing
> the final if I have to.  

[snip]

That sounds like a good idea.  I got into the
same habit when passing objects around in C++.

But this leads me to a question.

In C++, if I marked a parameter of a function as
'const', then I could not operate on that parameter
at all, no matter if I used pass by value or pass
by reference semantics, for objects or primitive
types.

However, in Java, when using the 'final' keyword in
method parameters for reference object types, it does
not provide the same protection, as the object can still
be modified, and only the reference itself can't be changed.

So my question question is:

How do you stop the modification of an object, via
the client working directly on the method parameter?

--
Chris
Lew - 12 Nov 2007 05:42 GMT
> How do you stop the modification of an object, via
> the client working directly on the method parameter?

Make the parameter be of an immutable type.

If you must use a mutable type, have the subroutine make a defensive copy of
the argument and work on that instead.

Signature

Lew

Curt Welch - 12 Nov 2007 06:15 GMT
> > How do you stop the modification of an object, via
> > the client working directly on the method parameter?
[quoted text clipped - 3 lines]
> If you must use a mutable type, have the subroutine make a defensive copy
> of the argument and work on that instead.

The object which is being passed must protect itself if it doesn't want to
be changed.  To start with, the instance vars can be changed to private or
protected to keep outside code from referencing or changing the instance
variables directly, and then the protection is a function of what methods
are available.  Making instance variables private by default is good
practice in general.

If the issue is that the calling object doesn't want the object passed to
be modified, there is no simple way to do it.  If possible, make a copy of
it before you pass it as Lew said.  Or you could wrap it in a wrapper class
which is a subclass of the object it is wrapping, and override all the
methods which mutate the object and disable them. But that's a excessive
measure if you only goal is to reduce the odds of bugs in the code.

There are no simple keywords like const to disable all modifications to a
passed argument.

Signature

Curt Welch                                            http://CurtWelch.Com/
curt@kcwc.com                                        http://NewsReader.Com/

Chris ( Val ) - 12 Nov 2007 06:15 GMT
> > How do you stop the modification of an object, via
> > the client working directly on the method parameter?
>
> Make the parameter be of an immutable type.

If I have control over the class design, I guess that is one way.

Or, did you perhaps mean to wrap up the object?

> If you must use a mutable type, have the subroutine make a defensive copy of
> the argument and work on that instead.

I was afraid of that, as it ultimately puts a
lot more responsibility on the developer.

Thank you.

--
Chris
Daniel Pitts - 12 Nov 2007 17:07 GMT
>> How do you stop the modification of an object, via
>> the client working directly on the method parameter?
[quoted text clipped - 3 lines]
> If you must use a mutable type, have the subroutine make a defensive
> copy of the argument and work on that instead.

Actually, in reality this defeats several OO principals.  If you think
of the method call as a message, then that message handler should be
free to issue other messages to any objects that it knows about.  If you
have a good design, then the handler (method) won't do something its not
supposed to.

Indeed, if you have an ill-behaved object that modifies its own state
when it shouldn't, then you need to make a defensive copy.

Well, that's true in theory at least. I haven't played around with that
concept, so take that advice with a grain of salt and think for yourself
what fits bets :-)

Daniel.

Signature

Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>

Lew - 12 Nov 2007 18:12 GMT
>>> How do you stop the modification of an object, via
>>> the client working directly on the method parameter?
[quoted text clipped - 9 lines]
> have a good design, then the handler (method) won't do something its [sic] not
> supposed to.

A good design might include making a defensive copy so that the handler method
won't do something it's not supposed to do.

There is no violation of "OO" principles there.

Signature

Lew

Taria - 13 Nov 2007 10:29 GMT
> > >Personally, I think it's odd that you have to make a copy of a passed
> > >parameter before using it to avoid modifying it within a method.  I
[quoted text clipped - 13 lines]
> modify it, I will normally create a new local variable and only modify the
> local variable.  

I definitely like that idea of making a local variable and only
modifying that instead of the passed variable.  I think I will adopt
this style.
Lew - 13 Nov 2007 13:43 GMT
> I definitely like that idea of making a local variable and only
> modifying that instead of the passed variable.  I think I will adopt
> this style.

public class Eg
{
  public static void modify( Foo foo )
  {
    Foo local = foo;
    local.setName( "bar" );
  }
}

If another method calls modify(Foo) then the name attribute of the passed
object will change.

public void cranitz()
{
  Foo arg = new Foo();
  arg.setName( "arg" );
  Eg.modify( arg );
  System.out.println( arg.getName() ); // displays "bar"
}

If the called method copies the passed object, then the method is unable to
alter the original object.  If it merely points a local variable to the
(mutable) passed object, naturally the method can alter the object through its
local pointer.

Signature

Lew



Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.