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 / August 2006

Tip: Looking for answers? Try searching our database.

reverse an array

Thread view: 
zero - 20 Aug 2006 09:47 GMT
Hi everyone,

I'm trying to reverse an array of bytes using Collections.reverse:

<code>
byte[] theBytes = { 1, 2, 3 };
System.out.println( Arrays.toString( theBytes ) );
Collections.reverse( Arrays.asList( theBytes ) );
System.out.println( Arrays.toString( theBytes ) );
</code>

However, his prints
[1, 2, 3]
[1, 2, 3]
ie, the array is not reversed at all.  When however I do the exact same
thing with a String array, it works:

<code>
String[] theStrings = { "Hello", "World" };
System.out.println( Arrays.toString( theStrings ) );
Collections.reverse( Arrays.asList( theStrings ) );
System.out.println( Arrays.toString( theStrings ) );
</code>

This gives the (expected) output:
[Hello, World]
[World, Hello]

What am I missing here?

TIA,
zero
Roland de Ruiter - 20 Aug 2006 10:29 GMT
> Hi everyone,
>
[quoted text clipped - 4 lines]
> Collections.reverse( Arrays.asList( theBytes ) );
> System.out.println( Arrays.toString( theBytes ) );
[...]
> String[] theStrings = { "Hello", "World" };
> System.out.println( Arrays.toString( theStrings ) );
// similar to:
// System.out.println( Arrays.toString( "Hello", "World"  ));
> Collections.reverse( Arrays.asList( theStrings ) );
// similar to:
// Collections.reverse( Arrays.asList( "Hello", "World" ) );
> System.out.println( Arrays.toString( theStrings ) );
[...]
> What am I missing here?

The Arrays.toString and Arrays.asList methods take a variable number of
arguments (varargs) of *reference types*, not of primitive types.

Compare it with the following, except you had just one element in
theByteArrays:

byte[] theBytes = { 1, 2, 3 };
byte[] theBytes2 = { 4, 5, 6 };
Object[] theByteArrays = {theBytes, theBytes2};
System.out.println(Arrays.deepToString(theByteArrays));
// similar to:
// System.out.println(Arrays.deepToString(theBytes, theBytes2));
Collections.reverse(Arrays.asList(theByteArrays));
// similar to:
// Collections.reverse(Arrays.asList(theBytes, theBytes2));
System.out.println(Arrays.asList(theByteArrays).size());
System.out.println(Arrays.deepToString(theByteArrays));

And print the size of the lists:
System.out.println(Arrays.asList(theBytes).size());
System.out.println(Arrays.asList(theStrings).size());
Signature

Regards,

Roland

zero - 20 Aug 2006 12:25 GMT
>> Hi everyone,
>>
[quoted text clipped - 18 lines]
> The Arrays.toString and Arrays.asList methods take a variable number of
> arguments (varargs) of *reference types*, not of primitive types.

Seems to me like the 1.5 release broke the Arrays.asList function.  
Compare the following two functions:

void test( int... list )
{
  System.out.println( list.getClass() );
}

void test( int[] list )
{
  System.out.println( list.getClass() );
}

Both will give the same output, indicating that a vararg of ints is
exactly the same as an array of ints, which is consistent with the
language guide documentation(1) which states: "It is still true that
multiple arguments must be passed in an array, but the varargs feature
automates and hides the process."

The signature of the Arrays.asList function is:
public static <T> List<T> asList(T... a)
Or, if T = int:
public static List<int> asList(int...a)
which should be completely equivalent with
public static List<int> asList(int[] a)
However, as my original post shows, passing an array of primitive values
results in a list of arrays, as if the signature were:
public static List<int[]> asList(int[] a)
or, equivalently:
public static List<int[]> asList(int... a)
and thus:
public static <T> List<T[]> asList(T... a)

If there is a flaw in my reasoning please let me know.  If not, this is
clearly a bug.

The documentation of the Arrays.asList function also states that its sole
argument is an array, consistent with the fact that varargs and arrays
are the same.  There is no mention of a difference between reference and
primitive types - and there should be no such difference.

(1) http://java.sun.com/j2se/1.5.0/docs/guide/language/varargs.html
Roland de Ruiter - 21 Aug 2006 00:10 GMT
>>> Hi everyone,
>>>
[quoted text clipped - 60 lines]
>
> (1) http://java.sun.com/j2se/1.5.0/docs/guide/language/varargs.html

The actual type argument cannot be a primitive type, only a reference
type (or a wildcard), see
<http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.5.1>
<http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.3>

So you cannot substitute T by int. A list of int, such as
   List<int> intList = new ArrayList<int>();
is invalid and won't compile.

Further, it is incorrect that a method *declaration* with a variable
number of arguments is equivalent to a method declaration with the
varargs replaced by the matching array type. For example
    public void foo(int... a) {} // *A*
is /not/ equivalent to
    public void foo(int[] a) {}  // *B*
because the call of method *B* only can take an int[] as actual
parameter (or null), whereas the call of method *A* can take an int[] or
a variable number of int's (possibly 0) as actual parameter:
    this.foo();                 // valid for *A*   invalid for *B*
    this.foo(1);                // valid for *A*   invalid for *B*
    this.foo(1,2,3);            // valid for *A*   invalid for *B*
    this.foo(new int[]{1,2,3}); // valid for *A*   valid for *B*
    this.foo(new int[0]);       // valid for *A*   valid for *B*

In your original example,
    byte[] theBytes = { 1, 2, 3 };
    Arrays.asList( theBytes );
the actual type argument T in
    public static <T> List<T> asList(T... a)
is not byte, but byte[]. The call
    Arrays.asList( theBytes );
therefore has only one argument (like this.foo(1)).
Signature

Regards,

Roland

Mike Schilling - 20 Aug 2006 23:19 GMT
> Hi everyone,
>
[quoted text clipped - 25 lines]
>
> What am I missing here?

Arrays.asList() taken an object arry, not an array of scalars.  Your program
doesn't even compile in JDK 1.4.

What's happening is apparently that, since theBytes is not the right sort of
array to be the argument to asList, variable-length argument semantics are
being applied, as if you'd coded

   Arrays.asList(o, p, q, r, s);

This would construct an array and then call the method, as if you'd coded

   Object[] arr = new Object[] {o, p, q, r, s};
   Arays.asList(arr);

Similarly, your code becomes (effectively)

   Object[] arr = new Object[] {theBytes};
   Arrays.asList(arr);

Obviously, sorting a one-member array won't do much.

You've found something truly ugly, by the way.  In 1.4, the compiler
correctly tells you that Arrays.asList can't be applied to an array of
scalars.  In 1.5, it silently does the wrong thing.


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



©2008 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.