toArray() of a map values

?

-

I have a LinkedHashMap that maps an Object (key) to a JButton (value).

Why does "(JButton[]) (map.values()).toArray();" produce a
ClassCastException?
 
A

Adam Maass

- said:
I have a LinkedHashMap that maps an Object (key) to a JButton (value).

Why does "(JButton[]) (map.values()).toArray();" produce a
ClassCastException?


Because toArray() with no args produces an Object[]. And your parens aren't
right. Try:

(JButton[])(map.values().toArray(new JButton[map.values().size()]));
 
R

Ross Bamford

- said:
I have a LinkedHashMap that maps an Object (key) to a JButton (value).

Why does "(JButton[]) (map.values()).toArray();" produce a
ClassCastException?


Because toArray() with no args produces an Object[]. And your parens aren't
right. Try:

(JButton[])(map.values().toArray(new JButton[map.values().size()]));

It's a common misconception that this method puts the values in the
array you give it, but this isn't true - instead it creates a new array
of the same type as the passed array.

If you're using this a lot, or in a loop, it's a lot better to simply
use:

private static final String[] PROTOARRAY = new String[0];

/* ... */

public String[] arrayList(ArrayList<String> ls)
{
return (ls.toArray(STRINGARRAY));
}

Cheers,
Ross
 
A

Alexey Dmitriev

Adam said:
- said:
I have a LinkedHashMap that maps an Object (key) to a JButton (value).

Why does "(JButton[]) (map.values()).toArray();" produce a
ClassCastException?



Because toArray() with no args produces an Object[]. And your parens aren't
right. Try:

(JButton[])(map.values().toArray(new JButton[map.values().size()]));
it's sufficient to pass array of zero length
for example: (JButton[])(map.values().toArray(new JButton[0]))
 
P

Patricia Shanahan

Ross said:
(JButton[])(map.values().toArray(new
JButton[map.values().size()]));


It's a common misconception that this method puts the
values in the array you give it, but this isn't true -
instead it creates a new array of the same type as the
passed array.

"If the collection fits in the specified array, it is
returned therein. Otherwise, a new array is allocated with
the runtime type of the specified array and the size of this
collection." (java.util.Collection javadoc for toArray with
a parameter).

This program prints "true":

import java.util.List;
import java.util.Arrays;

public class TestToArray {

public static void main(String[] args) {
String[] data = {"a","b","c"};
List l = (List) Arrays.asList(data);

String[] myArray = new String[l.size()];
String[] listArray = (String[])(l.toArray(myArray));

System.out.println(myArray==listArray);
}
}

I have never had to use one of these is a sufficiently
performance critical environment to care whether presizing
is faster or slower than using a zero-length array.


Patricia
 
F

Filip Larsen

Adam Maass wrote
(JButton[])(map.values().toArray(new JButton[map.values().size()]));

and Ross Bamford answered
It's a common misconception that this method puts the values in the
array you give it, but this isn't true - instead it creates a new array
of the same type as the passed array.

In the AbstractCollection implementation of toArray(Object[]) the array
passed in is indeed used if its size is equal to or greater than the
number of elements in the collection. When the size is greater the
remaining elements in the array are set to null and when the size is
less a new array of the right size with the same component type is
instantiated and used instead.

However, for completeness it should be noticed that the one-liner qouted
above is subject to standard synchronization issues. It will only will
work as expected if the map do not change size between the call to
map.values().size() and map.values().toArray(). If there are concurrent
modifications to the map the line above should be placed in a
synchronized(map) block or similar. When a zero-length prototype array
is used, the call must still be synchronized but now it can also be done
by using Collections.synchronizedMap() or similar.


Regards,
 
K

Kevin McMurtrie

Alexey Dmitriev said:
Adam said:
- said:
I have a LinkedHashMap that maps an Object (key) to a JButton (value).

Why does "(JButton[]) (map.values()).toArray();" produce a
ClassCastException?



Because toArray() with no args produces an Object[]. And your parens aren't
right. Try:

(JButton[])(map.values().toArray(new JButton[map.values().size()]));
it's sufficient to pass array of zero length
for example: (JButton[])(map.values().toArray(new JButton[0]))

Sufficient, but inefficient. A new array must be built through
reflection and the zero length array is discarded. It's also good to
start with a LinkedHashmap if serializing or iteration is a major
operation on a sparse Map.
 
K

Kevin McMurtrie

Esmond Pitt said:
Fred said:
Because you need more parenthesis:

((JButton[])(map.values())).toArray()

Actually he needs less:

(JButton[])map.values().toArray();

You're all nuts. AbstractMap returns Object[] unless you pass in an
array of what you want. The above can't be cast to anything.
 

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,768
Messages
2,569,574
Members
45,050
Latest member
AngelS122

Latest Threads

Top