1

I initially wanted to create a "method" Min, that will search the min of a an array and gives back two elements. One will represent the minimum value and the other the index of this value.In order to do that, I decided to create a class Min and a constructor with those two elements stored as instance variables accessible with getter and setter (a double and an int).

The tricky part is that then, I wanted to overload my class, and add a second constructor, this one will work with a 2D array as input and have two other instances variables ( a double[] and an int[]).

It is working, however I am uncomfortable, as I could create instance of this class for example with the first constructor, AND still have access to the two other variables that have no meaning to this constructor and vice versa.

I could have created a totally other class for my second constructor to solve this issue (ex: one class Min_array, and Min_2Darray), however I would like them to have the same name as it represent the same kind of operation.

I believe there should be a more elegant way for overloading and retrieve multiple results than the one I choose, I would be glad of some advices or to know what are your best practices. Thank you.

My second (more small) concern is that I had to create a lot of instances of constructor 1 in constructor 2 which seems to be quite odd and not efficient at all in term of memory allocation.

My class Min :

package operation;

public class Min {

    // ---------------- Instance Variables ------------------ 
    private int index = 0; 
    private double value = Double.POSITIVE_INFINITY; // important as i search for the MIN 
    private int[] ArrayIndex;   
    private double[] ArrayValue; 


    // ---------------- Constructor 01 ------------------ 
    public Min(double [] anArray) {
        for (int i = 0; i < anArray.length; i++) {
            if (anArray[i] < this.value) {
                this.value = anArray[i]; 
                this.index = i; 
            }
        }
    }

    // ---------------- Constructor 02 ------------------ 
    public Min(double [][] a2DArray, boolean accordingToRow) {

        int n_row = a2DArray.length; 
        int n_col = a2DArray[0].length; 

        if (accordingToRow == true) {
            this.ArrayIndex = new int [n_row]; 
            this.ArrayValue = new double [n_row];
            for (int i = 0; i < n_row; i++) {
                Min minofOneArray = new Min(a2DArray[i]);  // Here i call and create multiple instance of constructor 01.  
                this.ArrayIndex[i] = minofOneArray.getIndex(); 
                this.ArrayValue[i] = minofOneArray.getValue(); 
            }

        }else { // accordingToRow == false (so it according to Column now)
            
            this.ArrayIndex = new int [n_col]; 
            this.ArrayValue = new double [n_col]; 

            //need to loop to extract a column in this case
            double[] tmpArray = new double [n_row]; 

            for (int j = 0; j < n_col; j++) {
                for (int i = 0; i < n_row; i++) {
                    tmpArray[i] = a2DArray[i][j]; 
                }
                Min minofOneArray = new Min(tmpArray); 
                this.ArrayIndex[j] = minofOneArray.getIndex(); 
                this.ArrayValue[j] = minofOneArray.getValue(); 
            }

        }
        
    }

    // ---------------- Getters & Setters ------------------ 
    public int getIndex() {return this.index ; }
    public double getValue() {return this.value ; }

    public int[] getArrayIndex() {return this.ArrayIndex ; }
    public double[] getArrayValue() {return this.ArrayValue ; }

}

The test of my class Min :

package operation_test;

import java.util.Arrays;

import operation.Min;

class Test_MIN {
public static void main(String[] args) {
        
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>> Test of the Min Class <<<<<<<<<<<<<<<<<<<<<<<<<<" );

        
        double [] anArray = { 0,  2 , 1 , -2 , 5 };  
        
        Min minOfArray = new Min(anArray); 
        
        System.out.println(minOfArray.getIndex());
        System.out.println(minOfArray.getValue());
        System.out.println("--------------- End of test 01 -----------------" );
        
        double [][] a2DArray = {{0.2,5,-1},{1,3,0.5}};  
        
        // 0  5 -1
        // 1  3 0.5
        
        
        Min minOf2DArray = new Min(a2DArray, true); // according to row 
       
        System.out.println(Arrays.toString(minOf2DArray.getArrayIndex()));
        System.out.println(Arrays.toString(minOf2DArray.getArrayValue()));
        System.out.println("--------------- End of test 02 -----------------" );
        
        Min minOf2DArray_AccordingToCol = new Min(a2DArray, false); // according to column
           
        System.out.println(Arrays.toString(minOf2DArray_AccordingToCol.getArrayIndex()));
        System.out.println(Arrays.toString(minOf2DArray_AccordingToCol.getArrayValue()));
        System.out.println("--------------- End of test 03 -----------------" );
        

    }
}

The results of my class Min :

>>>>>>>>>>>>>>>>>>>>>>>> Test of the Min Class <<<<<<<<<<<<<<<<<<<<<<<<<<
3
-2.0
--------------- End of test 01 -----------------
[2, 2]
[-1.0, 0.5]
--------------- End of test 02 -----------------
[0, 1, 0]
[0.2, 3.0, -1.0]
--------------- End of test 03 -----------------
Chewbaka
  • 184
  • 10
  • 2
    If you want your different constructors to setup instances with different sets of instance variables, then you want to create instances of different classes. Those can inherit a base class with the common parts. The question needs details explaining why that is not an acceptable solution for you. – Yunnosch Jun 29 '20 at 16:55
  • Why return an object with the index and the element at the index when you can always just return the index and later use that index to access the element? You could just do `int min = arr[minIndex(arr)];` – user Jun 29 '20 at 16:56
  • Thank you for your answer, @Yunnosch, if so, I either have to create two distincts class or take care of not using the wrong getter. (I address this concern, because I am thinking about how other could use my code if I wanted to share it, and which way is the more "safe" to use and understand ?) . @ user, It think it is my wrong habbits comming from Matlab, however, indeed in this case it is not really usefull as you mentionned, but I still believe it can be interesting feature to have the possiblity of choosing? – Chewbaka Jun 29 '20 at 17:04
  • Is your comment just summarising your insight due to my comment (that is what it seems) or would you like me to explain something? If you perceive my comment as an answer (I was afraid to just phrase the obvious without helping you), I will turn it into an official answer, to make a complete Q/A pair. Let me know whether anything is missing to make it a satisfying answer. – Yunnosch Jun 29 '20 at 17:07
  • 1
    @user Just in case you did not notice. In a comment Op tried to ping you, but used incorrect @ syntax. – Yunnosch Jun 29 '20 at 17:11
  • @Yunnosch yes, it seems like that it is the case then, I will close the subject then. I know that those are two possible solutions, however I wondered if it there was not other or better solutions. As i dont have a big background in Java, for me it is kind of like 'the allegory of the cave' . – Chewbaka Jun 29 '20 at 17:15

2 Answers2

0

If you want your different constructors to setup instances with different sets of instance variables, then you want to create instances of different classes. Those can inherit a base class with the common parts.

(This, though very short, has been perceived as an answer by OP and @user. I create it to get the question out of the list of unanswered questions. Let me know when a more helpful or technically detailed answer is created. I don't mind deleting mine then.)

Yunnosch
  • 26,130
  • 9
  • 42
  • 54
0

I tried something different, It suits me a little bit better towards the concerns I expressed:

I post the code here if it can be useful to someone.

The idea is to use a class "tuple" to retrieve multiple outputs, and I therefore do not have the need to pass to constructor. I can still create one unique class that will have those two methods as static.

I however, still dont know which one is the best way, I suppose it depends on the means of application.

The class Tuple:

package utilitary;

public class Tuple<T, U> {
    private final T first;
    private final U second;

    public Tuple(T first, U second) {
        this.first = first;
        this.second = second;
    }

    public T getFirst() {
        return this.first;
    }

    public U getSecond() {
        return this.second;
    }

    @Override
    public String toString() { 
        return this.first + " " + this.second;
    }
}

My new class Min :

package operation;

import utilitary.Tuple;

public class Min {

    // ---------------- Method 01 ------------------ 
    public static Tuple<Integer, Double> Min_Array(double [] anArray) {
        int index = 0; 
        double value = Double.POSITIVE_INFINITY; // important as i search for the MIN 

        for (int i = 0; i < anArray.length; i++) {
            if (anArray[i] < value) {
                value = anArray[i]; 
                index = i; 
            }
        }
        return new Tuple<>(index, value);
    }

    // ---------------- Method 02 ------------------ 
    public static Tuple<int[], double[]> Min_2DArray(double [][] a2DArray, boolean accordingToRow) {

        int[] arrayIndex; 
        double[] arrayValue; 

        int n_row = a2DArray.length; 
        int n_col = a2DArray[0].length; 

        if (accordingToRow == true) {
            arrayIndex = new int [n_row]; 
            arrayValue = new double [n_row];
            for (int i = 0; i < n_row; i++) {

                Tuple<Integer, Double> minofOneArray = Min_Array(a2DArray[i]);  // Here i call method 01 multiple time 
                arrayIndex[i] = minofOneArray.getFirst(); 
                arrayValue[i] = minofOneArray.getSecond(); 
            }

        }else { // accordingToRow == false (so it according to Column now)

            arrayIndex = new int [n_col]; 
            arrayValue = new double [n_col]; 

            //need to loop to extract a column in this case
            double[] tmpArray = new double [n_row]; 

            for (int j = 0; j < n_col; j++) {
                for (int i = 0; i < n_row; i++) {
                    tmpArray[i] = a2DArray[i][j]; 
                }

                Tuple<Integer, Double> minofOneArray = Min_Array(tmpArray);  
                arrayIndex[j] = minofOneArray.getFirst(); 
                arrayValue[j] = minofOneArray.getSecond(); 
            }
        }
        return new Tuple<>(arrayIndex, arrayValue); 
    }

}

The test :

package operation_test;

import java.util.Arrays;

import operation.Min;
import utilitary.Tuple;

class Test_MIN {
public static void main(String[] args) {
        
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>> Test of the Min Class <<<<<<<<<<<<<<<<<<<<<<<<<<" );

        
        double [] anArray = { 0,  2 , 1 , -2 , 5 };  
        
        
        Tuple<Integer, Double> minOfArray = Min.Min_Array(anArray); 

        System.out.println(minOfArray.getFirst());
        System.out.println(minOfArray.getSecond());
        System.out.println("--------------- End of test 01 -----------------" );
        
        double [][] a2DArray = {{0.2,5,-1},{1,3,0.5}};  
        
        // 0.2  5 -1
        // 1  3 0.5
        
        Tuple<int[], double[]> minOf2DArray = Min.Min_2DArray(a2DArray, true); 
        
        System.out.println(Arrays.toString(minOf2DArray.getFirst()));
        System.out.println(Arrays.toString(minOf2DArray.getSecond()));
        System.out.println("--------------- End of test 02 -----------------" );
        
        
        Tuple<int[], double[]> minOf2DArray_AccordingToCol = Min.Min_2DArray(a2DArray, false); 
        
        System.out.println(Arrays.toString(minOf2DArray_AccordingToCol .getFirst()));
        System.out.println(Arrays.toString(minOf2DArray_AccordingToCol.getSecond()));
        System.out.println("--------------- End of test 03 -----------------" );
        
        

    }
}

The results

>>>>>>>>>>>>>>>>>>>>>>>> Test of the Min Class <<<<<<<<<<<<<<<<<<<<<<<<<<
3
-2.0
--------------- End of test 01 -----------------
[2, 2]
[-1.0, 0.5]
--------------- End of test 02 -----------------
[0, 1, 0]
[0.2, 3.0, -1.0]
--------------- End of test 03 -----------------
Chewbaka
  • 184
  • 10