Say we got 2 ordered collections of numbers. We want to compute the arithmetic difference element by element.
I think we need to use List of Number in order to model the idea of 'ordered collection of numbers'.
The problem is that the arithmetic difference (a banal '-' like in 3-2) is not defined for Number.
I can cast everything to Double, but I'd rather prefer a clean solution.
public static <E extends Number> List<E> listDifferenceElementByElement(List<E> minuend, List<E> subtrahend) throws Exception {
if (minuend.size() != subtrahend.size()) {
throw new Exception("Collections must have the same size"); //TODO: better exception handling
}
List<E> difference = new ArrayList<E>();
int i = 0;
for (E currMinuend : minuend) {
difference.add(currMinuend-subtrahend.get(i)); //error: The operator - is undefined for the argument type(s) E, E
i++;
}
return difference;
}
Any idea?
Since Number does not provide any subtract method, you can't do it simply. The alternatives I can think of are:
use the provided doubleValue() method, and return a double, but you could lose precision if the lists contain BigDecimal for example.
have one method per available Number subclass, but it could create a lot of duplicated code...
restrict the type to whatever makes sense (say double if precision does not matter too much or BigDecimal if it does), which is a subcase of (2).
Option 2 could be implemented like by replacing difference.add(currMinuend-subtrahend.get(i)); by difference.add(subtract(currMinuend, subtrahend.get(i)));
Then it's only a matter of writing 10 subtract methods:
private static int subtract(int a, int b) { return a - b; }
private static double subtract(double a, double b) { return a - b; }
private static BigDecimal subtract(BigDecimal a, BigDecimal b) { return a.subtract(b); }
etc.
This is nothing to do with generics, arrays, etc. Java doesn't allow operator overloading, so you cannot subtract 2 numbers with -, and the Number class doesn't define any methods for numeric operations. It can't because it might be operating on different subclasses (e.g. Integer.subtract(Double)) which would make defining the return type impossible.
You will need to use intrinsic types or BigDecimal (or similar) here, I think.
If you want to work with many arithmetic type, you can set your list as a generic list, then add the handler when you want to find the difference between them. The handler check if the type is instance of Double, Integer, or anything you want. Based on each type, you could compute the difference.
Related
I am trying to create a generic class in Java that will perform operations on numbers. In the following example, addition, as follows:
public class Example <T extends Number> {
public T add(T a, T b){
return a + b;
}
}
Forgive my naivety as I am relatively new to Java Generics. This code fails to compile with the error:
The operator + is undefined for the argument type(s) T, T
I thought that with the addition of "extends Number" the code would compile. Is it possible to do this Java or will I have to create overridden methods for each Number type?
Number does not have a + operator associated with it, nor can it since there is no operator overloading.
It would be nice though.
Basically, you are asking java to autobox a descedant of Number which happens to include Integer, Float and Double, that could be autoboxed and have a plus operator applied, however, there could be any number of other unknown descendants of Number that cannot be autoboxed, and this cannot be known until runtime. (Damn erasure)
Your problem is not really related to generics, rather to operators, primitives vs objects, and autoboxing.
Think about this:
public static void main(String[] args) {
Number a = new Integer(2);
Number b = new Integer(3);
Number c = a + b;
}
The above does not compile
public static void main(String[] args) {
Integer a = new Integer(2);
Integer b = new Integer(3);
Number c = a + b;
}
The above does compile, but only because of autoboxing - which is kind of a hacky syntax glue introduced in Java 5, and only works (in compile time) with some concrete types : int-Integer for example.
Behind the scenes, the Java compiler is rewriting the last statement ("I must unbox a and b to apply the sum operator with primitive datatypes, and box the result to assign it to object c") thus:
Number c = Integer.valueOf( a.intValue() + b.intValue() );
Java can't unbox a Number because it does not know at compile time the concrete type and hence it cannot guess its primitive counterpart.
You can do something like this
class Example <T extends Number> {
public Number add(T a, T b){
return new Double(a.doubleValue() + b.doubleValue());
}
}
Yes, Nathan is correct. If you want something like this, you have to write it yourself
public class Example <T extends Number> {
private final Calculator<T> calc;
public Example(Calculator<T> calc) {
this.calc = calc;
}
public T add(T a, T b){
return calc.add(a,b);
}
}
public interface Calculator<T extends Number> {
public T add(T a, T b);
}
public class IntCalc implements Calculator<Integer> {
public final static IntCalc INSTANCE = new IntCalc();
private IntCalc(){}
public Integer add(Integer a, Integer b) { return a + b; }
}
...
Example<Integer> ex = new Example<Integer>(IntCalc.INSTANCE);
System.out.println(ex.add(12,13));
Too bad Java has no type classes (Haskell) or implicit objects (Scala), this task would be a perfect use case...
There are similar questions to this one, and the answer is you can't do it like that.
You could check if a and b are an instance of Long/Double/Integer/etc. and delegate the add to methods like:
public Integer add(Integer a, Integer b) {
return a+b; // this actually uses auto boxing and unboxing to int
}
And you would need to create one for every type that extends Number, so that's not really feasible. In other words, don't use generics for numeric operations. Number as a superclass is pretty limited.
Consider Example<Number>, how would + work on that? There is no add or similar in Number or even the likes of Integer.
Worse consider final class FunkyNumber extends Number { ... weird stuff, no add op ... }.
Even the java runtime library has this problem, most of the methods dealing with primitives have to duplicate the same functionality.
The fastest option would be to write your code for one type and then copy it and replace the type to generate the methods for the other types. A short script should be enough to do this.
I am trying to write a method that will find the difference between elements of two arrays of the same length and here is what I did until now:
public static <T extends Object> T method(T[] array,T[] array1){
T[]difference;
difference = new T[array.length]; //error :generic array creation
for(int i=0;i<array.length;i++){
difference[i]=array[i]-array1[i]; //error:bad operand types for binary operator
}
return (T)difference;
}
but it constantly returns to me a message that i wrote next to the line of the code that it refers to
There are two problems with your code:
Java doesn't support generic array creation. You can get round this by creating an array of Objects and then casting.
The bigger problem is that java doesn't support operator overloading, and subtraction (i.e. -) is only supported by primitive types. This is compouded by the fact that generics doesn't support primitive types, which makes what you're trying to do impossible on its own.
To get round these problems, you'd need to do a number of things:
Don't use primitives, but you can used boxed types instead (so instead of int you'd use Integer, etc.).
You need to tell your function how to find the difference between two objects of the required type. You can achieve this by defining a 'Subtractor' interface.
I'd also suggest using lists instead of arrays, as these handle generics much more nicely. You can easily convert between lists and arrays afterwards if needed.
So, as a skeleton of a solution, here's what I'd propose:
Define a generic interface for finding differences:
interface Subtractor<T> {
T subtract(T a, T b);
}
Rewrite your method to use lists, and to take a subtractor as an argument:
public static <T> List<T> difference(
List<? extends T> listA, List<? extends T> listB, Subtractor<T> subtractor) {
int resultSize = Math.min(listA.size(), listB.size());
List<T> result = new ArrayList<>(resultSize);
for(int i=0; i<resultSize; ++i) {
result.add(subtractor.subtract(listA.get(i), listB.get(i)));
}
return result;
}
Define subtractor implementations for the types you want to be able to use the method with:
class IntSubtractor implements Subtractor<Integer> {
#Override
Integer subtract(Integer a, Integer b) {
return Integer.valueOf(a.intValue() - b.intValue());
}
}
Use your method. You can use Arrays.asList for turning arrays into lists, but you can't use arrays of primitives unfortunately.
Integer[] a = new Integer[]{5,6,7,8};
Integer[] b = new Integer[]{1,2,3,4};
Integer[] c = difference(Arrays.asList(a), Arrays.asList(b), new IntSubtractor())
.toArray(new Integer[4]);
I assume that your array values are numbers. It is difficult to provide a general solution. But I would say this might work for your case:
public static <T extends Number> Number[] method(T[] array, T[] array1){
Number[]difference = new Number[array.length];
for(int i=0; i< array.length; i++){
difference[i]= Double.valueOf(array[i].doubleValue() - array1[i].doubleValue());
}
return difference;
}
My CustomNumber class extends the Number class (implements all the method, but not listed here). The class has a division method, which should work as the following: I can give to it any type of Number argument, and always get a the calculation without precision loss. That is why I'm thinking about double values. But in this case, I can't call this method with anything else, but Double Objects. How can I make this method, any maybe the whole class 100% generic?
public class CustomNumber<T> extends java.lang.Number {
java.lang.Number value;
public CustomNumber(java.lang.Number value) {
this.value = value;
}
public static CustomNumber<Double> division(Number a, Number b) {
return new CustomNumber<>(a.doubleValue() / b.doubleValue());
}
}
In this respect, Java is extremely annoying.
They dogmatically disallowed operator overloading (although Scala has it), so you are compelled to code / into a method called divide or similar, and so on.
For more specifics see how the arbitrary precision libraries such as BigInteger are implemented, and base your solution from that.
One a plus point in Java, you might get away with using BigDecimal and doing away with your idea entirely. Although the code you end up with when performing complex mathematical operations with it is practically unreadable. (For this reason I resort to using C++ with a JNI).
If this was what you were trying, it doesn’t work:
CustomNumber<Integer> quotient = division(5, 3);
We get “Type mismatch: cannot convert from CustomNumber<Double> to CustomNumber<Integer>”. For an obvious reason. Even though the numbers you tried to divide were autoboxed into Integer.
The straightforward solution is to drop the generics completely:
public class CustomNumber extends java.lang.Number {
// ...
public static CustomNumber division(Number a, Number b) {
return new CustomNumber(a.doubleValue() / b.doubleValue());
}
}
Now we have no problem doing:
CustomNumber quotient = division(5, 3);
System.out.println(quotient);
With an appropriate toString method in your class this should print:
1.6666666666666667
java.lang.Number offers very few methods. Division, for instance, doesn't really do the same thing for each type. 1.0d/2.0d is 0.5d but 1/2 is 0. So you're going have to decide which you're doing. Also note the double does not exactly represent long or, say, BigInteger.
To map various forms of numbers to your common interpretation, you'll need an adapter layer. There may be ore than one way to map a numeric type.
public interface CustomNumber<THIS extends CustomNumber<THIS>> {
THIS divide(THIS other);
}
public final class LongNumber extends CustomNumber<LongNumber> {
// (Note, you don't actually need to overload this,
// but it does prevent the likes of LongNumber.of(aDouble).)
public static LongNumber of(Long value) {
return new LongNumber(value);
}
public static LongNumber of(AtomicLong value) {
return new LongNumber(value);
}
private final Number value;
private LongNumber(Number value) {
this.value = value;
}
#Override public LongNumber divide(LongNumber other) {
return this.longValue() / other.longValue();
}
}
You might want to have an adapter for the same types that deal with, say, bankers' rounding. I don't want to even think about how to implement that. Or full on saturated arithmetic. So here's is a sign preserving alternative implementation (still does division by zero):
#Override public SignPreservingLongNumber divide(
SignPreservingLongNumber other
) {
long dividend = this.longValue();
long divisor = other.longValue();
return (
dividend == Long.MIN_VALUE &&
divisor == -1
) ? Long.MAX_VALUE : dividend/divisor;
}
I've defined a Point class like this.
class Point<E,F> {E x; E y; ...}
so that i can give float, Integer ... [anyway its a number]
But when i want to manipulate its an error.
void getdistance(Point<Number, Number> pt) {
this.x-pt.x.floatValue(); //not a statement
this.y-pt.y.floatValue();
}
also i should not give string as type, so should i change it to Number?
or any other way to calculate distance from generic type?
But if i change the type to Number how can i specify different co-ordinate type [float or integer]?
how to infer type here?
this.y-pt.y.TypeValue?
how can we do if its integer or double?
when i pass
pt.getdistance(otherpt);
compiler shows error: create a method getdistance(Float,Integer). how to pass other point to that method?
Try and define your point like this: Point<E extends Number, F extends Number>.
That way the compiler can tell that E and F both are numbers.
However, you might even want to simplify that to Point<N extends Number> since most likely both coordinates should be of the same type (i.e. Double, Integer etc.) - mixing types seems quite odd to me.
The method would then have to be adjusted:
<X extends Number, Y extends Number> float getdistance(Point<X, Y> pt) {
float dx = this.x.floatValue() - pt.x.floatValue();
float dy = this.y.floatValue() - pt.y.floatValue();
return (whatever your distance calculation needs to look like);
}
Note that x and y might be null, thus you'd have to check for that.
Specifying X and Y here would allow you to pass a Point<Float, Integer> to a Point<Double, Long>'s member method. You could redefine E and F here, but that might be a source of confusion.
Edit:
I'll elaborate a bit on Mark Peters' comment:
Using floatValue() or even doubleValue() might result in a loss of precision, since even double would not be able to accurately represent each long value. Thus you might experience severe precision losses, especially with higher numbers.
Additionally, BigInteger and BigDecimal are numbers too and those have even higher precision.
In order to get maximum precision, you'd have to use BigDecimal in the calculation and when creating the initial values you'd have to check the types of the values and call the appropriate method:
for Byte, Short, Integer and Long you'd call BigDecimal.valueof( x.longValue() )
for Float and Double you'd call BigDecimal.valueof( x.doubleValue() )
BigDecimal could be used as is
BigInteger would be passed to the BigDecimal constructor
This would add quite a bit of complexity and in that case you might want to go with arshajii's suggestion of subclassing Point instead.
You can tell the types that they should extend Number with:
<T extends Number, T1 extends Number>
This way you'll be able to pass it Float etc
I am trying to create a generic class in Java that will perform operations on numbers. In the following example, addition, as follows:
public class Example <T extends Number> {
public T add(T a, T b){
return a + b;
}
}
Forgive my naivety as I am relatively new to Java Generics. This code fails to compile with the error:
The operator + is undefined for the argument type(s) T, T
I thought that with the addition of "extends Number" the code would compile. Is it possible to do this Java or will I have to create overridden methods for each Number type?
Number does not have a + operator associated with it, nor can it since there is no operator overloading.
It would be nice though.
Basically, you are asking java to autobox a descedant of Number which happens to include Integer, Float and Double, that could be autoboxed and have a plus operator applied, however, there could be any number of other unknown descendants of Number that cannot be autoboxed, and this cannot be known until runtime. (Damn erasure)
Your problem is not really related to generics, rather to operators, primitives vs objects, and autoboxing.
Think about this:
public static void main(String[] args) {
Number a = new Integer(2);
Number b = new Integer(3);
Number c = a + b;
}
The above does not compile
public static void main(String[] args) {
Integer a = new Integer(2);
Integer b = new Integer(3);
Number c = a + b;
}
The above does compile, but only because of autoboxing - which is kind of a hacky syntax glue introduced in Java 5, and only works (in compile time) with some concrete types : int-Integer for example.
Behind the scenes, the Java compiler is rewriting the last statement ("I must unbox a and b to apply the sum operator with primitive datatypes, and box the result to assign it to object c") thus:
Number c = Integer.valueOf( a.intValue() + b.intValue() );
Java can't unbox a Number because it does not know at compile time the concrete type and hence it cannot guess its primitive counterpart.
You can do something like this
class Example <T extends Number> {
public Number add(T a, T b){
return new Double(a.doubleValue() + b.doubleValue());
}
}
Yes, Nathan is correct. If you want something like this, you have to write it yourself
public class Example <T extends Number> {
private final Calculator<T> calc;
public Example(Calculator<T> calc) {
this.calc = calc;
}
public T add(T a, T b){
return calc.add(a,b);
}
}
public interface Calculator<T extends Number> {
public T add(T a, T b);
}
public class IntCalc implements Calculator<Integer> {
public final static IntCalc INSTANCE = new IntCalc();
private IntCalc(){}
public Integer add(Integer a, Integer b) { return a + b; }
}
...
Example<Integer> ex = new Example<Integer>(IntCalc.INSTANCE);
System.out.println(ex.add(12,13));
Too bad Java has no type classes (Haskell) or implicit objects (Scala), this task would be a perfect use case...
There are similar questions to this one, and the answer is you can't do it like that.
You could check if a and b are an instance of Long/Double/Integer/etc. and delegate the add to methods like:
public Integer add(Integer a, Integer b) {
return a+b; // this actually uses auto boxing and unboxing to int
}
And you would need to create one for every type that extends Number, so that's not really feasible. In other words, don't use generics for numeric operations. Number as a superclass is pretty limited.
Consider Example<Number>, how would + work on that? There is no add or similar in Number or even the likes of Integer.
Worse consider final class FunkyNumber extends Number { ... weird stuff, no add op ... }.
Even the java runtime library has this problem, most of the methods dealing with primitives have to duplicate the same functionality.
The fastest option would be to write your code for one type and then copy it and replace the type to generate the methods for the other types. A short script should be enough to do this.