Vector to array?

W

wang

Hi all,
I've tried to use Vector.toArray() to copy the content of a vector
to an array without success. The vector contains only object of
the class MyClass. I've made the following attempts:

MyClass[] arr = new MyClass[myVector.size()];
arr = (MyClass)myVector.toArray();

or:
arr = (MyClass[])myVector.toArray();

or:
arr = myVector.toArray(arr);

How should the method toArray() be used? Thanks in advance!

k.w.wang
 
M

Mat

wang said:
Hi all,
I've tried to use Vector.toArray() to copy the content of a vector
to an array without success. The vector contains only object of
the class MyClass. I've made the following attempts:

MyClass[] arr = new MyClass[myVector.size()];
arr = (MyClass)myVector.toArray();

or:
arr = (MyClass[])myVector.toArray();

or:
arr = myVector.toArray(arr);

How should the method toArray() be used? Thanks in advance!

k.w.wang
I don't know exactly why, but I use :

MyClass[] arr;
arr = (MyClass[])myVector.toArray(new MyClass[myVector.size()]);


Mat
 
M

Massimo Dell'Andrea

Mat said:
I don't know exactly why, but I use :

MyClass[] arr;
arr = (MyClass[])myVector.toArray(new MyClass[myVector.size()]);


Mat

or
MyClass[] arr = (MyClass[])myVector.toArray(new MyClass[0]);

or
MyClass[] arr = (MyClass[])myVector.toArray(new MyClass[]{});

or
MyClass[] arr = new MyClass[myVector.size]);
myVector.toArray(arr);
 
M

Monique Y. Mudama

Hi all,
I've tried to use Vector.toArray() to copy the content of a vector
to an array without success. The vector contains only object of
the class MyClass. I've made the following attempts:

MyClass[] arr = new MyClass[myVector.size()];
arr = (MyClass)myVector.toArray();

or:
arr = (MyClass[])myVector.toArray();

or:
arr = myVector.toArray(arr);

How should the method toArray() be used? Thanks in advance!

k.w.wang

This doesn't directly answer your question, but that new is
unnecessary. You're allocating memory, then instantly dropping your
only reference to it.
 
B

Babu Kalakrishnan

Massimo said:
Mat said:
I don't know exactly why, but I use :

MyClass[] arr;
arr = (MyClass[])myVector.toArray(new MyClass[myVector.size()]);


Mat


or
MyClass[] arr = (MyClass[])myVector.toArray(new MyClass[0]);

or
MyClass[] arr = (MyClass[])myVector.toArray(new MyClass[]{});

or
MyClass[] arr = new MyClass[myVector.size]);
myVector.toArray(arr);

Solutions (1) and (2) are really not worth using because they
(unnecessarily) create an extra Array object. The third solution
(assuming that you correct it by replacing "size" with "size()") is
indeed the best solution - it's actually the same as what Mat proposed,
since the API guarantees that the argument passed will be returned with
the values filled in if the Collection will fit into it.

BK
 
M

Monique Y. Mudama

MyClass[] arr = new MyClass[myVector.size()];
arr = (MyClass)myVector.toArray();

Without paying any attention to whether or not the desired result is
accomplished, it looks to me like the reference arr is being assigned
to a new array, and then immediately reassigned to a different array.
So the new array is simply being

I see what you mean now. It is not just he keyword "new" you would
delete, but that whole line and just collapse it to:

MyClass[] arr = (MyClass)myVector.toArray();

This code won't work. The cast will fail since toArray without a model
to follow, will produce an Object[].

Oh.

I thought this was a newbie "defensive new" thing. Instead, you're
saying that the quoted code works, and more importantly if you remove
the new, it doesn't?

Now I'm the one who's feeling like a newbie, because I find that to be
really bizarre. Granted, I've never played with toArray(), but ...

Well, I guess now I have to.
You would have to write that as

MyClass[] arr = (MyClass) myVector.toArray( new MyClass[
myVector.size() ] );

With generics you could drop the cast, and clever folk might prune it
even further.

What I think the OP meant to say was:

MyClass[] arr = new MyClass[ myVector.size() ];
arr = (MyClass) myVector.toArray( arr );

or perhaps:
MyClass[] arr = new MyClass[ myVector.size() ];
myVector.toArray( arr );

The first code will work even if the size is off a tad. The second
will not.
 
H

Hemal Pandya

Roedy said:
I see what you mean now. It is not just he keyword "new" you would
delete, but that whole line and just collapse it to:

MyClass[] arr = (MyClass)myVector.toArray();

This code won't work.

It won't even compile, it converts an Object to an Array. Or am I
missing something?
 
T

Thomas Weidenfeller

Monique said:
MyClass[] arr = new MyClass[myVector.size()];
arr = (MyClass)myVector.toArray();


Without paying any attention to whether or not the desired result is
accomplished, it looks to me like the reference arr is being assigned
to a new array, and then immediately reassigned to a different array.

Not necessarily.
So the new array is simply being allocated, then immediately lost to
eventually be snagged by the GC.

Am I missing something?

You are missing how Vector.toArray() works. If the Vector fits in the
supplied array, it will *return a reference to the supplied array*!
toArray() will only allocate a new array if the Vector doesn't fit.

There are basically two tricks to use toArray successfully:

1) Supply an array of the desired type. Otherwise, if you use the
version of the toArray() method with doesn't require an argument, you
get an Object[].

2) Supply a large enough array. Otherwise toArray() will allocate an
new array (but at least of the supplied type).

Ok, and of course, if you run in a multithreaded environment, you need
to take care of locking/protecting the Vector when you do this.

/Thomas
 
R

Roedy Green

MyClass[] arr = (MyClass)myVector.toArray();

This code won't work. The cast will fail since toArray without a model
to follow, will produce an Object[].

Oh.

I thought this was a newbie "defensive new" thing. Instead, you're
saying that the quoted code works, and more importantly if you remove
the new, it doesn't?


That code on the top line will fail. The problem is toArray not know
the type of the thing on the right, so all it can do is produce an
Object[] filled with MyClasses, which is a totally different animal
that a MyClass[] filled with MyClasses. It can't be cast to
MyClass[].

If you give it a MyClass[] the right size to fill, or even an exemplar
empty MyClass[] array, then it knows the desired type of array.
 
T

Thomas Hawtin

Thomas said:
You are missing how Vector.toArray() works. If the Vector fits in the
supplied array, it will *return a reference to the supplied array*!
toArray() will only allocate a new array if the Vector doesn't fit.
Ok, and of course, if you run in a multithreaded environment, you need
to take care of locking/protecting the Vector when you do this.

Not entirely. The worst that could happen, would be some nulls on the
end of the array.

The toArray is an atomic operation, so no need to worry about that. If
the Vector grows between finding it's size and toArray, then the array
gets reallocated. If it shrinks, you just get a few nulls at the end.
(The reference immediately after the end of the valid values is always
set to null, even if it wasn't before.)

Tom Hawtin
 
R

Roedy Green

MyClass[] arr = (MyClass)myVector.toArray();

This code won't work.

It won't even compile, it converts an Object to an Array. Or am I
missing something?

The following analogous program will compile, but it fails with a
CastCastException on run.

import java.util.ArrayList;
public class CastExper
{
/**
* test harness
*
* @param args not used
*/
public static void main ( String[] args )
{
ArrayList a = new ArrayList(10);
a.add( "elephant" );
a.add( "beanbag" );
String[] things = (String[])a.toArray();
for ( String thing: things )
{
System.out.println( thing );
}
}
}

This is how you would do it with generics

import java.util.ArrayList;
public class CastExper
{
/**
* test harness
*
* @param args not used
*/
public static void main ( String[] args )
{
ArrayList<String> a = new ArrayList<String>(10);
a.add( "elephant" );
a.add( "beanbag" );
String[] things = a.toArray( new String[ a.size() ] );
for ( String thing: things )
{
System.out.println( thing );
}
}
}


The following code will not compile, even though you would think
toArray could, if it were written differently, might take advantage of
its knowledge that a was an ArrayList<String>. toArray() is defined
without any generics. Because of type erasure, that knowledge is
useless in determining the actual return type. The information is
not around at run time to instantiate the precisely correct type of
array.

String[] things = a.toArray();
 
H

Hemal Pandya

Roedy said:
MyClass[] arr = (MyClass)myVector.toArray();

This code won't work.

It won't even compile, it converts an Object to an Array. Or am I
missing something?

The following analogous program will compile,

Yes it will, because it does not have the erroneous conversion from
Object[] to Object.
This is how you would do it with generics

You had earlier mentioned that the case is not required with generics,
but it wasn't clear to me how. Thank you for this explanation.
 
R

Roedy Green

Yes it will, because it does not have the erroneous conversion from
Object[] to Object.

What code are you referring to? It is quite legal to cast an Object[]
to Object.
 
R

Roedy Green

MyClass[] arr = new MyClass[myVector.size()];
arr = (MyClass)myVector.toArray();


Without paying any attention to whether or not the desired result is
accomplished, it looks to me like the reference arr is being assigned
to a new array, and then immediately reassigned to a different array.

Not necessarily.
So the new array is simply being allocated, then immediately lost to
eventually be snagged by the GC.

Am I missing something?

You are missing how Vector.toArray() works. If the Vector fits in the
supplied array, it will *return a reference to the supplied array*!
toArray() will only allocate a new array if the Vector doesn't fit.

I think you may have overlooked the fact that in that particular
example he failed to pass the array to toArray(). So allocation was
pointless.
 
M

Monique Y. Mudama

MyClass[] arr = (MyClass)myVector.toArray();
[snip]

That code on the top line will fail. The problem is toArray not
know the type of the thing on the right, so all it can do is produce
an Object[] filled with MyClasses, which is a totally different
animal that a MyClass[] filled with MyClasses. It can't be cast to
MyClass[].

If you give it a MyClass[] the right size to fill, or even an
exemplar empty MyClass[] array, then it knows the desired type of
array.


That strikes me as relying on a side effect to have the code function.
Isn't that bad design?
 
R

Roedy Green

If you give it a MyClass[] the right size to fill, or even an
exemplar empty MyClass[] array, then it knows the desired type of
array.


That strikes me as relying on a side effect to have the code function.
Isn't that bad design?

The term side effect usually refers to a method changing something not
one of the inputs or outputs. What do you mean by that term?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top