Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java subtracting Generic values The operator minus is undefined

Tags:

java

generics

I am trying to subtract the value from a provided array (2D Array). I would like to do by using Generics. Can anyone help what is wrong with my code. I mean do I need to extend some class? I am getting the error (The operator - is undefined for the argument type(s) T, T)

Thanks in advance.

//this method Subtracts Value from the given Matrix for all the rows but for given columns 
private <T> void subtractValueFromColumns(T[][] matrix,
        ArrayList<Integer> columnsIndex, T value) {

    for(int i = 0; i < matrix.length; i++){
        for(int j = 0; j < columnsIndex.size(); j++){
            matrix[i][j] = matrix[i][j] - value;
        }
    }

}
like image 407
Waqar Detho Avatar asked Nov 05 '14 10:11

Waqar Detho


People also ask

How do you add two generic values in Java?

You have to add the numbers as the same type, so you could do x. intValue() + y. intValue(); .

Can you do int minus double?

For example, it's totally okay to subtract an int from a double or float, since those data types will maintain the precision.


2 Answers

You can't do it without casting (which more or less means that Generics is useless here).

The - operator can be only applied to numeric types, but at compile-time the compiler cannot be aware of the runtime type of the generic type T.


As a workaround I can suggest using the BigDecimal type and it's nested arithmetic methods (like .subtract())

private void subtractValueFromColumns(BigDecimal[][] matrix,
        ArrayList<Integer> columnsIndex, BigDecimal value) {
    for(int i = 0; i < matrix.length; i++){
        for(int j = 0; j < columnsIndex.size(); j++){
            matrix[i][j] = matrix[i][j].subtract(value);
        }
    }
}

This has a downside effect, though. In order to use the method properly, you will be forced to convert your numeric variables to BigDecimal and vice-versa

like image 146
Konstantin Yovkov Avatar answered Oct 30 '22 00:10

Konstantin Yovkov


You need to define operations and methods that can be used on that given type.

public interface ArithmeticOps<T extends ArithmeticOps<T>>
{
    T add(T other);
    T subtract(T other);
    T divide(T other);
    T multiply(T other);
}

private <T extends ArithmeticOps<T>> void subtractValueFromColumns(T[][] matrix,
        List<Integer> columnsIndex, T value) {
    for(int i = 0; i < matrix.length; i++){
        for(int j = 0; j < columnsIndex.size(); j++){
            matrix[i][j] = matrix[i][j].subtract(value);
        }
    }
}

It is similar to how LibGDX does its Vector operations.

https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/math/Vector.java

 public interface Vector<T extends Vector<T>> {
    /** Scales this vector by a scalar
     * @param scalar The scalar
     * @return This vector for chaining */
    T scl (float scalar);

    T add (T v);
}

and

https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/math/Vector2.java

public class Vector2 implements Serializable, Vector<Vector2> {
    @Override
    public Vector2 scl (float x, float y) {
        this.x *= x;
        this.y *= y;
        return this;
    }

    @Override
    public Vector2 add (Vector2 v) {
        x += v.x;
        y += v.y;
        return this;
    }
}
like image 43
EpicPandaForce Avatar answered Oct 29 '22 23:10

EpicPandaForce