EnlightenedFunky
EnlightenedFunky

Reputation: 325

Method Overloading Techinques

I have a method overload that goes as follows:

public class Odddetector {

    public static void main(String[] args) {
        int count = countOdd(new int [] {5, 7, 3, 9, 0});
        System.out.println(count);
        count = countOdd(new int [] {2, 6, 4, 8, 1});
        System.out.println(count);
        count = countOdd(5, 7, 10);
        System.out.println(count);
        count = countOdd(8, 2, 7);
        System.out.println(count);
        count = countOdd(new int[][] {{1, 2}, {3, 4, 5}});//extra point only
        System.out.println(count);
        count = countOdd(new int[][] {{6, 2}, {3, 4, 0}});//extra point only
        System.out.println(count);
    }
public static int countOdd(int[] a){
      int count=0;
      for (int i: a) count = (i %2 != 0)?++count:count;
      return count;
      // Do Something;
}
public static int countOdd(int[][] a){
     // Do Something;
     int count=0;
     for (int b = 0; b< a.length; b++){
            //System.out.println(java.util.Arrays.toString(a[b])); not a necessary line.
            count += countOdd(a[b]);
        }
      return count;
}
// more method overloading

My question is there a way to condense the solution to have one method that takes into account N-Dimensional Arrays. The code runs fine like this however, I would like to know what Java techniques can help account for the increase in dimensions. I would like to add some details and that is that the first method is the base method, and all the other methods call that first int[] a. The new section I added is the full code I am currently in developing this code which my professor gave as a challenge. I currently have the Data Structures by Lang, and I can accept hints. I prefer hints actually because I would like to learn to code this.

Upvotes: 1

Views: 130

Answers (2)

Vasily Liaskovsky
Vasily Liaskovsky

Reputation: 2538

Well, I guess there are some very interesting problems around, all coupled together. Namely

  1. How to generify array processing and method declaration for arbitrary depth (this is your initial question)?
  2. How to deep traverse array with unknown depth?
  3. How to inject some useful payload into array traversal (in your case - count odd numbers) independently of traversal itself?
  4. Is it possible to generify approach for primitive and object arrays, and how?

I have a good suggestion for points 3: instead of hardcoding payload in the method itself we can produce IntStream (or generic Stream for Object version) which can be processed separately.

On points 1 and 4 my guess it's probably not possible or at least not elegant. java.lang.reflect.Array doesn't show any wonder in this and my assumption is - if JDK couldn't do this, I cannot neither. So, the best option is probably to allow general signature with Object accompanied with couple of frequently used overloads, up to depth 3. Of course, this implies danger of ClassCastExceptions at runtime.

So, final result with implementation of point 2 may look like this

public class FlattenArray {
  public static IntStream flatten(int n) {
    return IntStream.of(n);
  }
  public static IntStream flatten(int[] array) {
    return IntStream.of(array);
  }
  public static IntStream flatten(int[][] array) {
    return flatten((Object) array);
  }
  public static IntStream flatten(Object array) {
    Class<?> aClass = array.getClass();
    if (!aClass.isArray())
      return IntStream.of(((Number) array).intValue());
    else {
      Class<?> componentType = aClass.getComponentType();
      if (componentType.isPrimitive())
        return IntStream.of((int[]) array);
      else
        return Arrays.stream((Object[]) array).flatMapToInt(FlattenArray::flatten);
    }
  }
}

And use this like

long count = FlattenArray.flatten(2, 3, 5, 7).filter(i -> i & 1 != 0).count();

Upvotes: 1

001
001

Reputation: 13533

When the parameter is amulti dimensional array, you can recursively call the function that digs down until you end up with a 1d array of numbers. The logic is:

if a is a multi-dimensional array
    for each array in a
        call recursively
else
    count odd numbers in a

I have 2 functions. One that takes a variable number of args, and a recursive one. The first just calls the second with the var args as an array. The varargs function needs a bit of work if you want to allow mixed parameters (eg: countOdd(new int [] {1,2,3}, 4, 5);)

// The var args version. You call this. It then calls the recursive
// version.
public static <T> int countOdd(T... arguments)
{
   return countOddRec(arguments);
}

// Recursive version
private static <T> int countOddRec(T[] a)
{
    if (a == null || a.length == 0) return 0;
    
    int count=0;

    // Is it an array of Numbers?
    if (a[0] instanceof Number) {
        for (T i: a) {
            // Simplified the counting code a bit. Any # mod 2 is either 0 or 1
            count += ((Number)i).intValue() % 2;
        }
    }
    // Is it an multi-dimensional? Call recursively for each sub-array.
    else {
        for (T sub : a) {
            count += countOddRec((T[])sub);
        }
    }
    
    return count;
}

As mentioned in the comments, this will not work for primitive data types (ex: int, etc). Instead, use non-primitive types (ex: Integer, etc).

Upvotes: 2

Related Questions