Newbie Question - ArrayLists and methods  
Author Message
Taria





PostPosted: 2007-11-11 18:46:00 Top

java-programmer, Newbie Question - ArrayLists and methods 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





PostPosted: 2007-11-11 22:26:00 Top

java-programmer >> Newbie Question - ArrayLists and methods Taria wrote:
> 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<List<Integer>> table = new ArrayList<List<Integer>>();

> 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);

... 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:");
> 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){

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);
> items.remove(lParen);
> items.add(lParen,c);
> }
> return items;
> }
> }

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.

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





PostPosted: 2007-11-12 0:18:00 Top

java-programmer >> Newbie Question - ArrayLists and methods Joshua Cranmer wrote:
> 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
> {
> List< List <Integer> > table
> = new ArrayList< ArrayList <Integer> > ();
>
> public Matriculate()
> {
> // the table will now contain zero rows
> assert table.size() == 0;
>
> // here row is declared the one and only time
> // and initialized for the first of more than one time
> List <Integer> row = new ArrayList <Integer> ();
> row.add( 1 );
> row.add( 2 );
> row.add( 3 );
> row.add( 5 );
>
> table.add( row );
>
> // the table will now contain one row
> assert table.size() == 1;
>
> row = new ArrayList <Integer> ();
> // notice - re-used, not re-declared
> // the variable 'row' now points to a whole
> // new ArrayList
> row.add( 1 );
> row.add( 2 );
> row.add( 4 );
> row.add( 8 );
> row.add( 16 );
>
> table.add( row );
>
> // the table will now contain two rows
> assert table.size() == 2;
> }
> // now the variable 'row' is out of scope
> // the closing curly brace killed it
>
> public List< List <Integer>> getTable()
> {
> return Collections.unmodifiableList( table );
> }
> }

--
Lew
 
 
Taria





PostPosted: 2007-11-12 1:22:00 Top

java-programmer >> Newbie Question - ArrayLists and methods 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





PostPosted: 2007-11-12 6:01:00 Top

java-programmer >> Newbie Question - ArrayLists and methods Taria wrote:
> 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)
>
>
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.


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





PostPosted: 2007-11-12 7:11:00 Top

java-programmer >> Newbie Question - ArrayLists and methods On Sun, 11 Nov 2007 09:22:14 -0800, Taria <email***@***.com> wrote,
quoted or indirectly quoted someone who said :

>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
--
Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com
 
 
Roedy Green





PostPosted: 2007-11-12 7:13:00 Top

java-programmer >> Newbie Question - ArrayLists and methods On Sun, 11 Nov 2007 14:00:41 -0800, Daniel Pitts
<email***@***.com> 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
--
Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com
 
 
curt





PostPosted: 2007-11-12 8:10:00 Top

java-programmer >> Newbie Question - ArrayLists and methods Roedy Green <email***@***.com> wrote:
> On Sun, 11 Nov 2007 09:22:14 -0800, Taria <email***@***.com> wrote,
> quoted or indirectly quoted someone who said :
>
> >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

--
Curt Welch http://CurtWelch.Com/
email***@***.com http://NewsReader.Com/
 
 
Roedy Green





PostPosted: 2007-11-12 8:24:00 Top

java-programmer >> Newbie Question - ArrayLists and methods On 12 Nov 2007 00:10:25 GMT, email***@***.com (Curt Welch) wrote, quoted
or indirectly quoted someone who said :

>
>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".
--
Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com
 
 
Daniel Pitts





PostPosted: 2007-11-12 8:30:00 Top

java-programmer >> Newbie Question - ArrayLists and methods Roedy Green wrote:
> On 12 Nov 2007 00:10:25 GMT, email***@***.com (Curt Welch) wrote, quoted
> or indirectly quoted someone who said :
>
>> 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".
True that.

--
Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
 
 
Chris ( Val )





PostPosted: 2007-11-12 13:31:00 Top

java-programmer >> Newbie Question - ArrayLists and methods On Nov 12, 11:24 am, Roedy Green <email***@***.com>
wrote:
> On 12 Nov 2007 00:10:25 GMT, email***@***.com (Curt Welch) wrote, quoted
> or indirectly quoted someone who said :
>
>
>
> >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.

[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?

 
 
Lew





PostPosted: 2007-11-12 13:43:00 Top

java-programmer >> Newbie Question - ArrayLists and methods Chris ( Val ) wrote:
> 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.

--
Lew
 
 
Chris ( Val )





PostPosted: 2007-11-12 14:16:00 Top

java-programmer >> Newbie Question - ArrayLists and methods On Nov 12, 4:42 pm, Lew <email***@***.com> wrote:
> Chris ( Val ) wrote:
>
> > 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.

 
 
curt





PostPosted: 2007-11-12 14:16:00 Top

java-programmer >> Newbie Question - ArrayLists and methods Lew <email***@***.com> wrote:
> Chris ( Val ) wrote:
> > 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.

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.

--
Curt Welch http://CurtWelch.Com/
email***@***.com http://NewsReader.Com/
 
 
Daniel Pitts





PostPosted: 2007-11-13 1:08:00 Top

java-programmer >> Newbie Question - ArrayLists and methods Lew wrote:
> Chris ( Val ) wrote:
>> 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.
>
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.

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





PostPosted: 2007-11-13 2:12:00 Top

java-programmer >> Newbie Question - ArrayLists and methods Daniel Pitts wrote:
> Lew wrote:
>> Chris ( Val ) wrote:
>>> 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.
>>
> Actually, in reality this defeats several OO principals [sic]. 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 [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.

--
Lew
 
 
Taria





PostPosted: 2007-11-13 18:29:00 Top

java-programmer >> Newbie Question - ArrayLists and methods On Nov 11, 2:10 pm, email***@***.com (Curt Welch) wrote:
> Roedy Green <email***@***.com> wrote:
> > On Sun, 11 Nov 2007 09:22:14 -0800, Taria <email***@***.com> wrote,
> > quoted or indirectly quoted someone who said :
>
> > >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 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





PostPosted: 2007-11-13 21:43:00 Top

java-programmer >> Newbie Question - ArrayLists and methods Taria wrote:
> 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.

--
Lew