2

I have a Rational number class with a construtor with a default value of 0/1 called like this:

public Rational (){ this(0, 1);}

public Rational (int numerator, int denominator){
    this.numerator = numerator;

    if (denominator== 0)
        throw new IllegalArgumentException("Denominator can't be zero.");

    this.denominator = denominator;
}

Now, in a subclass, I want to create an array of Rationals. They come all set to "null". So I have two methods inside the Rational class that set all values to zero. I have one for a simple array and another for a matrix:

public Rational[] zero(Rational[] array){
    for (int i=0; i<array.length; i++)
        array[i] = new Rational();

    return array;
}

public Rational[][] zero (Rational[][] matrix){
    for (int i=0; i<matrix.length; i++)
        for(int j=0; j<matrix[i].length; j++)
            matrix[i][j] = new Rational();

    return matrix;
}

First, would it be better to used improved loops? Something like:

public Racional[][] zero(Racional[][] matrix){
    for (Racional[] arr : matrix)
        for (Racional rat : arr)
            rat = new Rational();

    return matrix;
}

Second, is there a way to create an array or matrix without having to manually zero all the positions as we can do with primitive types.

e.g.:

int[] arr = new int [10];            //All zero
Rational[] arr = new Rational [10];  //All null
arr = arr.zero (arr);                //All "default" - 0/1
3
  • Sorry, but Java doesn't do that as far as I am aware. Commented Mar 29, 2016 at 17:41
  • For primitive types, you can use Arrays.fill. Commented Mar 29, 2016 at 17:44
  • @callyalater Arrays.fill() works for objects also, but it is applicable here only if Rational is immutable. Commented Mar 29, 2016 at 17:45

2 Answers 2

1

If you work heavily with arrays and matrices of Rational, consider writing static helper methods in Rational class:

static public Rational[] newArray(int size) {
    Rational[] arr = new Rational[size];
    for (int i = 0; i < size; i++)
        arr[i] = new Rational();
    return arr;
}

static public Rational[][] newMatrix(int h, int w) {
    Rational[][] m = new Rational[h][];
    for (int i = 0; i < h; i++) 
        m[i] = newArray(w);
    return m;
}

Then, to instantiate an array or matrix filled with default instances, just call:

Rational[] array = Rational.newArray(10);

or

Rational[][] matrix = Rational.newMatrix(10, 5);
Sign up to request clarification or add additional context in comments.

1 Comment

Yep. Works just fine. And it is simple to understand.
1

Using an immutable Rational class,

public static class Rational {
    public final int num, denom;
    public Rational() {num = denom =0;}
    public Rational(int num, int denom) {this.num=num; this.denom=denom;}
}

It can be done like this:

public static void zero(Rational[][] mat) {
    Rational def = new Rational();
    for (Rational[] arr : mat) {
        Arrays.fill(arr, def);
    }
}
public static void main (String[] args) throws java.lang.Exception
{
    Rational[][] mat = new Rational[5][5];
    zero(mat);
}

"Automatic" default initialization something like C++ is not possible here. Also, your nested "new-style" for loops don't work because setting rat = new Rational() only reassigns the temporary, rat, not the value in the array.

As you can see, this fills the matrix with the same default Rational. This is an obvious performance and memory-use optimization with immutable Rational, and avoids repeated constructor calls. If you have mutable Rational (which I would discourage), this is almost certainly catastrophically wrong: changing one value will change them all. In this case, you will probably do best with the nested "old-style" for loops. (I think an outer "new-style" for loop with an inner "old-style" for loop would not be as easy to read, but is certainly feasible.)

9 Comments

@SashaSalauyou I think you commented before I edited my answer to include that information :-)
As Rational is mutable, I have something like this when I try to multiply: this.numerator = this.numerator * otherRational.numerator; (same for denominator). And void as return. So, If I go for immutable, I should change like this int num = this.numerator * otherRational.numerator; and then I return a Rational as return new Rational (num, den);. Right? Wise to do it like this?
@J.F. That's how to do it. It is often wise to do it this way, but it's up to you. For instance, java.lang.Stringdoes everything this way, but you have to decide if this suits your needs. Read comments on programmers.stackexchange.com/questions/151733, and maybe codebetter.com/patricksmacchia/2008/01/13/… for more.
@J.F. the only exception to this rule is java.util.Date, but mutablility of Date is considered a design flaw, and all mutation methods there are deprecated.
@SashaSalauyou Indeed. Three .valueOf() methods in BigDecimal. And all methods have a "non-void" return.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.