How to combine similar Java functions into one (in C ++ I would use templates)

In one of my Java classes, I have two very similar functions. Is there a way in Java to combine them into one function, so I don't need to support 2 functions?

public static boolean areValuesValid( double [] values, int numElements ) { if( values == null || values.length != numElements ) { return false; } for( int i = 0; i < numElements; ++i ) { if( Double.isNaN( values[i] ) ) { return false; } } return true; } public static boolean areValuesValid( float [] values, int numElements ) { if( values == null || values.length != numElements ) { return false; } for( int i = 0; i < numElements; ++i ) { if( Float.isNaN( values[i] ) ) { return false; } } return true; } 
+6
source share
3 answers

This is not an ideal scenario, for the reasons described in @ericbn. But here is one way to avoid most of the duplication with lambda:

 public static boolean areValuesValid( double [] values, int numElements ) { return areValuesValid(values, numElements, i -> !Double.isNaN(values[i])); } public static boolean areValuesValid( float[] values, int numElements ) { return areValuesValid(values, numElements, i -> !Float.isNaN(values[i])); } private static boolean areValuesValid( Object values, int numElements, IntPredicate tester ) { if( values == null || Array.getLength(values) != numElements ) { return false; } for( int i = 0; i < numElements; ++i ) { if( !tester.test(i) ) { return false; } } return true; } 
+4
source

Your question is somewhat difficult for Java:

  • double and float are primitive types, and therefore they are not part of the class hierarchy. The double and float shells extend Number , which extends Object , but
  • An array of primitive types does not match an array of objects, and Java, for example, does not use autobox a float[] to float[] .
  • There is no isNan(Number n) or isNan(Object o) method in the Java API, but the ones you used that expect a double or float . However, you can do Double.isNan(n.doubleValue()) for any Number n .

TL DR In Java, the usual practice for primitive types is to have separate implementations for each of them, just like you.

EDIT: As @azurefrog suggested:

 public static boolean areValuesValid(Number[] values, int numElements) { if (values == null || values.length != numElements) { return false; } for (Number value : values) { if (Double.isNaN(value.doubleValue())) { return false; } } return true; } 

And then you have to use Apache Commons ArrayUtils :

 public static boolean areValuesValid(double[] values, int numElements) { return areValuesValid(ArrayUtils.toObject(values), numElements); } public static boolean areValuesValid(float[] values, int numElements) { return areValuesValid(ArrayUtils.toObject(values), numElements); } 

EDIT2: The @shmosel solution passes the array as an Object , and from here avoids converting the entire array to a box type. A solution worth considering is to avoid this overhead.

+5
source

To simplify things, I would use an instance:

  public static boolean areValuesValid( Object[] values ) { if ( values == null ) { return false; } for( int i = 0; i < values.length; ++i ) { //if not Float and not Double return false if ( values[i] instanceof Float || values[i] instanceof Double) { return true; } } return false; } 

I'm not sure if you really have to go through numElements.

-3
source

All Articles