4

I'm trying to write a function that accept an array and return an array in different order.

It works with int, double, string, object or any object in an array.

Follow are the sample of the function for String.

public String[] randomize(String[] array, int randomKey)
{
    //algorithm here
    return newStringArray;
}

For all the Object type, I know I can do it like

public Object[] randomize(Object[] array, int randomKey)
{
    //algorithm here
    return newObjectArray;
}

Instead of boxing all the primitive type into an object, is there any other method I can just write the algorithm once and without creating function for each primitive array? Is there a generic array type that work for objects AND primitive?

Thanks

P.S. Do not want to use autoboxing because of the performance penalty. Quote from [autoboxing]: http://docs.oracle.com/javase/1.5.0/docs/guide/language/autoboxing.html

It is not appropriate to use autoboxing and unboxing for scientific computing, or other performance-sensitive numerical code.

Chun
  • 43
  • 4

6 Answers6

3

Sadly generics won't work here as generics do not cover primitives but they do cover primitive arrays. Primitive arrays are also not autoboxed into a wrapper class array. That is something you would have to do manually, but that is very very slow. One solution is to provide an override for each primitive, similar to how Arrays.sort is implemented. This creates a lot of duplicate code. Another solution is to use an Array interface similar to ArrayList that emulates an Array, get/set methods for indices, and provide subclasses for each primitive and one for objects. You can then use the Array interface and not care what the actual type is.

Smith_61
  • 2,078
  • 12
  • 12
0

Try using a standard container class such as ArrayList. These now work with primitives (by automatically treating them as wrapper objects, e.g. Integer) and any other objects.

Debasis
  • 3,680
  • 1
  • 20
  • 23
  • You're kinda wrong. `ArrayList` (or other generic class) cannot work with primitives even in Java 8. Just try to compile this class: `public class Test { java.util.ArrayList list; } ` – Dmitry Ginzburg Aug 13 '14 at 08:46
  • No i didn't mean that.. what i meant was you can declare an arraylist of integers as ArrayList a, and then you can put primitive integers in it... e.g. a.add(5).. you don't need to do the explicit typecasting by a.add(new Integer(5)) – Debasis Aug 13 '14 at 11:05
  • 1
    Okay, that's called [autoboxing](http://docs.oracle.com/javase/tutorial/java/data/autoboxing.html). – Dmitry Ginzburg Aug 13 '14 at 12:15
0

If you want to pass primitive type to your method , then you have to write a method for each primitive type , there is no way to do it with just one method , and i think that if is there a way,then we would find it in some example in the Java API ,but if we check for example Arrays , there is Arrays.copyOf method for each primitive.

Mifmif
  • 3,132
  • 18
  • 23
0

There is an option using reflection, but you will loose all means of type safety in this case:

public Object randomize(Object array, int randomKey) {
  if (array.getClass().isArray()) {
    int length = Array.getLength(array);
    for (int i = 0; i < length; i ++) {
      Object arrayElement = Array.get(array, i);
      // do something with array
    }
    return // result
  } else {
    throw new IllegalArgumentException();
  }
}

This implementation makes use of the fact that even an int[] inherits from Object.

Alternatively, you could overload your function in order to convert each primitive array type implicitly to a boxed version.

public int[] randomize(int[] array, int randomKey) {
  return toIntArray(randomize(toIntegerArray(array), randomKey));
}

This is a known limitation of the Java type system and it is currently adressed by the JVM's architects. There was a great presentation at this year's JVMLS on this matter. The presentation will be online somewhen in September.

Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192
  • I dont want to using boxing and unboxing due to the performance costs associated with boxing and unboxing. Do you know if the reflection will have a big performance impact on the code? – Chun Aug 13 '14 at 08:50
  • Short answer: Yes. For array-related reflection, the JVM does not know a concept of *inflation* as it does for reflective method invocation. Instead, the read is performed per `native` invocation. This means that the JVM can not longer inline the call once the `randomize` method gets hot and cannot optimize it as well as it normally would. With the second suggestion to overload the method, this can be done since no calls are `native`. As a matter of fact, the JVM will probably do an escape analysis and remove the intermediate boxing altogether what results in non-boxed performance. – Rafael Winterhalter Aug 13 '14 at 08:57
0

Is there a generic array type that work for objects AND primitive?

No.

However, you can use wrapper classes for primitives to achieve what you need. Thanks to autoboxing, there is no need to explicit creation of Wrapper object.

Kao
  • 7,225
  • 9
  • 41
  • 65
0

I will say this straight up: No.

See Why don't Java Generics support primitive types?

Because the type of the data would need to be inferred, you can't just randomly place some boolean in, say an int type. They would have to be wrapped and caster back, because Java is a type-safe language (well... Kind of)

Generics is about as close as you are able to get to an "all-in-one" we are talking here. AFAIK, the autobox and auto-unbox overhead has a negligible impact on performance anyways.

Community
  • 1
  • 1