In the code below Comparable interface is used to ensure x and y should be of same reference type but as V is extending T so V should be of the same type as T or subclass of T then what is the point of using Comparable interface.
Also if I am not using Comparable interface then the last call to isIf method is getting compile despite x and y are of different types.
Can anyone explain the use Comparable interface regarding this program?
public class Generics_13 {
static <T extends Comparable<T>, V extends T> boolean isIn(T x, V[] y) {
for(int i = 0;i < y.length;i++)
if(x.equals(y[i])) return true;
return false;
}
public static void main(String[] args) {
Integer nums[] = {10, 20, 30};
if(isIn(10, nums))
System.out.println("10 belongs to the array");
if(!isIn(60, nums))
System.out.println("70 doesnt belong to the array");
String arr[] = {"Neeraj", "Parth", "Ritum"};
if(!isIn("abc", arr))
System.out.println("abc doesnt belongs to the array");
/*if(isIn("String", nums)) // illegal
System.out.println("This wont compile");
*/
}
}
The current use of generics doesn't really makes sense, because no method from Comparable is ever used, which means that you could simply remove the extends declaration.
Also the Type V is also not used, as you can simply replace it by T and not break your logic. so the final result would look like this:
public class Generics_13 {
static <T> boolean isIn(T x, T[] y) {
for(int i = 0;i < y.length;i++)
if(x.equals(y[i])) return true;
return false;
}
// main() etc follow here
}
But now that we have the Stream API in java-8 you can use the following snippet to achieve the same thing:
static <T> boolean isIn(T x, T[] y) {
return Arrays.stream(y).anyMatch(i -> i.equals(x));
}
The comparable here in your scenario is optional.
T extends Comparable<T>
What this means is that whatever value you are passing should implement the interface comparable.
which basically means that the type parameter can be compared with other instances of the same type.
Now you might be wondering that since you are passing primitive data types, then how does the code not throw an error?
The reason for this is that the primitives are autoboxed to wrapper objects which implement Comparable.
So your ints become Integer and String is already an object both of which implement Comparable.
PS : your code will also work for objects provided that the class implements comparable
Related
I keep getting a message telling me that the operator < is undefined for the types T,T. This is happening around
if(index<lowest)
How would I go about modifying my program so that I could get the smallest and largest values of an array list using a generic method?
package p07;
import java.util.ArrayList;
public class MyList<T extends Number> {
private ArrayList<T> l;
public MyList(ArrayList<T> l) {
this.l=l;
}
public void add(T x) {
l.add(x);
}
public static <T> void smallest(ArrayList<T> l) {
T lowest=l.get(0);
for(T index:l) {
if(index<lowest) {
}
}
}
}
The compiler is right: the operator < is only applicable to primitive numeric type. Quoting section 15.20.1 of the JLS:
The type of each of the operands of a numerical comparison operator must be a type that is convertible (§5.1.8) to a primitive numeric type, or a compile-time error occurs.
Hence, it is not defined for Objects, not even for Numbers, because they cannot be unboxed to a primitive type: section 5.1.8 of the JLS:
A type is said to be convertible to a numeric type if it is a numeric type (§4.2), or it is a reference type that may be converted to a numeric type by unboxing conversion.
What you need is to use a Comparator or make your objects Comparable. Comparators are responsible for comparing two objects of the same type. Since the objects here are Numbers, and they are not Comparable, you need to use a custom Comparator, like this:
Comparator<Number> myComparator = new Comparator<Number>() {
#Override
public int compareTo(Number n1, Number n2) {
// implement logic here.
// Return -1 if n1 < n2, 0 if n1 = n2, 1 if n1 > n2
}
};
Then you can use this comparator like this:
public static <T extends Number> T smallest(List<T> l) {
T lowest = l.get(0);
for (T index : l) {
if (myComparator.compareTo(index, lowest) < 0) {
index = lowest;
}
}
return lowest;
}
(Note that I added T extends Number to the type of the method - that is because the method is static so it's in fact declaring another type T that the one the class is).
There are several things awry here, but let's start with the low-hanging syntax fruit.
The arithmetic operators only work for primitive values, and T is very much an Object, so you wouldn't be able to use them here.
Another nuance to your syntax is that you're T for that static function is not the same as the T which is bound to your class.
You can fix that, either by adding the bound yourself...
public static <T extends Number> void smallest(ArrayList<T> l)
...but this leads me to ask, why would you want this method to be static at all?
You're obscuring the name of the field l with the parameter l, so while you may think that this is going to work for the instance's provided l, it won't since the method itself is declared static, and you'd still be shadowing the field's name if it weren't.
What you should do is remove static from that method, and remove the parameter from the function.
public void smallest() {}
But now, you've got an issue in that you don't actually return what the smallest value is. You should return it instead of nothing:
public T smallest() {}
Getting the last value out of an array is straightforward if you're capable of sorting. You just need to ensure that all of your elements are Comparable so that they can be sorted, and the values you care about the most - like Integer, Double, Float, Long - are.
public class MyList<T extends Number & Comparable<T>> {}
If you can sort, then getting the smallest is straightforward:
public T smallest() {
// Don't mutate the order of the original array.
ArrayList<T> listCopy = new ArrayList<>(l);
Collections.sort(listCopy);
return listCopy.get(0);
}
Getting the highest via this approach I leave as an exercise for the reader.
So I have 2 versions of the same method.
Version 1:
public static <T> int countGreaterThan(T[] anArray, T elem)
{
int count = 0;
for (T e : anArray)
{
if (e > elem)
count++;
}
return count;
}
Version 2:
public static <T extends Comparable<T>> int countGreaterThan(T[] anArray, T elem)
{
int count = 0;
for (T e : anArray)
{
if (e.compareTo(elem) > 0)
count++;
}
return count;
}
Eclipse complains about Version 1 because the > operator can only be used when comparing primitives, which makes sense to me.
So to fix this problem, the internet tells me to use a type parameter bounded by the Comparable interface. This is where I start to lose grasp of what's going on...
From my basic understanding of interfaces, a class that implements an interface must provide a method body for each of the methods declared in the interface.
Thus, why doesn't Version 2 have to look like this?
public int compareTo(T o)
{
//stuff for method body
}
public static <T extends Comparable<T>> int countGreaterThan(T[] anArray, T elem)
{
int count = 0;
for (T e : anArray)
{
if (e.compareTo(elem) > 0)
count++;
}
return count;
}
^I get that this isn't correct syntax, but I just did it to illustrate my question as to why I don't have to write a method body for the method in the Comparable interface in this situation.
Please try to keep the explanation in Layman's terms. I've been teaching myself this stuff, so simple explanations help me understand the more technical side of topics when I research them further.
Sorry for the confusion, let me clarify.
Here is the code for the Comparable interface:
public interface Comparable<T> {
public int compareTo(T o);
}
There is no method body for compareTo() because it's an interface. Why don't I have to manually write a body for compareTO() so I can use the interface in my countGreaterThan() method?
Is it because the interface is part of the Java Collections Framework (if that's why please explain how that works)
Here's a different situation where I create my own interface:
public interface Dance { //an interface
public void boogie(int count);
}
and in order to implement that interface in different classes I need to write method bodies in those classes for the method in the dance interface.
public class theMoonwalk implements Dance {
public void boogie(int count) {
System.out.println("Slide " + count + " times!");
}
public void mJ() {
System.out.println("Michael Jackson did this dance!");
}
public class theHustle implements Dance {
public void boogie(int steps) {
System.out.println("Step " + steps + " times!");
}
}
public class theJitterBug implements Dance {
public void boogie(int twists) {
System.out.println("Twist " + twists + " times!");
}
}
Why don't I have to write a method body for compareTo() (because a method body is not included in the Comparable interface for compareTo() )?
The type that T ultimately refers to has to implement Comparable<T>, not the class that you're declaring the type bound on.
To make it a bit simpler: in order to use your countGreaterThan method, whatever objects are contained in your array and in your elem argument must be a Comparable object.
This means that an invocation like this is acceptable:
Integer[] foo = {1, 2, 3, 4, 5};
YourClass.countGreaterThan(foo, 2);
Your type is bound to Integer, and Integer implements Comparable<Integer>.
This is not acceptable:
Object[] bar = {new Object(), new Object(), new Object()};
YourClass.countGreaterThan(bar, new Object());
Your type is bound to Object, and Object does not implement Comparable. The same logic applies to a custom object that you implement; if it isn't bound to Comparable, then it's not going to be in the proper bound.
I am trying to understand bounded types and not quite grasping the point of them.
There is an example of bounded generics on which provides this use case:
public class NaturalNumber<T extends Integer> {
private T n;
public NaturalNumber(T n) { this.n = n; }
public boolean isEven() {
return n.intValue() % 2 == 0;
}
// ...
}
If you are going to restrict the classes that can be the parameterized type, why not just forget the parameterization all together and have:
public class NaturalNumber {
private Integer n;
public NaturalNumber(Integer n) { this.n = n; }
public boolean isEven() {
return n.intValue() % 2 == 0;
}
// ...
}
Then any class that extends/implements Integer can be used with this class.
Also, a side question: How is T extending Integer in the first example when the Java Integer class is final?
How is T extending Integer in the first example when the Java Integer class is final?
T can only be Integer, so the "extends" here is purely symbolic. (I'm starting with the side-note because, indeed, it's an example where generics are useless. I truly have no idea why the tutorial thinks this is an informative demonstration. It's not.)
Suppose instead that T extends Number:
class Example<T extends Number> {
private T num;
void setNum(T num) { this.num = num; }
T getNum() { return num; }
}
So the point of generics in general, is that you can do this:
Example<Integer> e = new Example<>();
e.setNum( Integer.valueOf(10) );
// returning num as Integer
Integer i = e.getNum();
// and this won't compile
e.setNum( Double.valueOf(10.0) );
Generics are a form of parametric polymorphism, essentially it lets us reuse code with a generality regarding the types involved.
So what's the point of a bound?
A bound here means that T must be Number or a subclass of Number, so we can call the methods of Number on an instance of T. Number is unfortunately a generally useless base class on its own (because of precision concerns), but it might let us do something interesting like:
class Example<T extends Number> extends Number {
// ^^^^^^^^^^^^^^
...
#Override
public int intValue() {
return num.intValue();
}
// and so on
}
It's more common, for example, to find T extends Comparable<T> which lets us do something more meaningful with T. We might have something like:
// T must be a subclass of Number
// AND implement Comparable
Example<T extends Number & Comparable<T>>
implements Comparable<Example<T>> {
...
#Override
public int compareTo(Example<T> that) {
return this.num.compareTo(that.num);
}
}
And now our Example class has a natural ordering. We can sort it, even though we have no idea what T actually is inside the class body.
If we combine these concepts, that:
generics allow the "outside world" to specify an actual type and
bounds allow the "inside world" to use a commonality,
we could build constructs such as:
static <T extends Comparable<T>> T min(T a, T b) {
return (a.compareTo(b) < 0) ? a : b;
}
{
// returns "x"
String s = min("x", "z");
// returns -1
Integer i = min(1, -1);
}
If I have a class that uses a template <T> how do I compare two variables of type T? One of my friends told me that you should add <T extends Comparable<? super T>> to your class in order to compare type T variables, but I dont competely understand what he ment. Here is my class:
public class SomeClass<T extends Comparable<? super T>>
{
public SomeClass(){}
public T foo(T par, T value)
{
if(value > par)
{
return value
}
else
{
return par;
}
}
}
And in my Main.java:
SomeClass<Integer> sc = new SomeClass<Integer>();
Integer val1 = 10;
Integer val2 = 5;
System.out.println(sc.foo(val1, val2));
The error i get is:
error: bad operand types for binary operator '>' if(value > par)
Your T implements Comparable, so you should use its compareTo() method.
if (value.compareTo(par) > 0) {
....
}
Also, note that in java it is called Generics, and not Templates, and is quite different from C++ templates (much weaker and much less complicated from the C++ version). One important difference is it does not work on primitives, only on objects - so if you wanted to use SomeClass<int> - that's impossible. (You could use SomeClass<Integer> however).
Also note, you cannot assign
T = 0;
Since T is an object.
> operator can be used only on primitives and not on objects. You need to use compareTo method for comparing objects.
I am following practices of coding to an interface in java as I learn it. I have a Function interface that has an executeFunction() method. But I would like to make this method generic. So the client can pass in a list of Strings, Boolean, Integers, Doubles etc. to run aggregate computation on them.
But I don't have a good grasp of generics so I would like some advice and an explanation of what the design approach I am in the process of coding is actually capable of doing. I'm thinking of having a StatsFunctions and ArithmeticFunctions concrete implementation classes that could be injected in other classes to use their fucntionalit. (Sorta trying the Strategy Pattern).
Here is my code:
import java.util.List;
public interface Function {
public <T> double executeFunction(List<T> vector);
}
The Question:
1). How can I use/alter this interface above to make it as generic and dynamic as possible?
If you could provide some examples of using this, it would be a huge help for my learning.
2). Why can't I do the below? I am getting an error saying: The operator "+" is undefined for the argument type T.
public class ArithmeticFunctions implements Function {
#Override
public <T> double executeFunction(List<T> vector) {
int retVal = 0;
for (int i = 0; i < vector.size(); i++) {
retVal = vector.get(i) + retVal;
}
return retVal;
}
}
Thank you in advance.
Better yet ::
public interface Function<F, T> {
T apply(F input);
}
Use it like this::
Function<Integer, Integer> doubleMyInput = new Function<Integer, Integer>() {
#Override
public Integer apply(Integer input) {
return input * 2;
}
};
The answer to the second question is not that simple. The error you see is a consequence of type erasure (this is how generics are implemented on the JVM).
Basically, your generic function declaration is equivalent to the following ::
public <T extends Object> double executeFunction(List<T> vector);
And the Java runtime does not see your type declarations, it only sees Objects.
To understand more clearly, let's assume that we are working in java 1.4, when generics didn't exist. Your interface would then look like this ::
public interface MyFunction {
public double executeFunction(List vector);
}
And the implementation ::
public class ArithmeticFunction implements MyFunction {
public double executeFunction(List vector) {
double retVal = 0;
for (int i = 0; i < vector.size(); i++) {
retVal += (((Double)vector.get(i))).doubleValue();
}
return retVal;
}
}
Note the cast, since there is really no other way to retrieve the value.
You can then do this ::
ArithmeticFunction af = new ArithmeticFunction();
// Good
af.executeFunction(new ArrayList(Arrays.asList(new Double[] {new Double(1), new Double(2)})));
However, this is also possible, and will get you a ClassCastException at runtime ::
// Bad !!
af.executeFunction(new ArrayList(Arrays.asList(new String[] {"A", "B", "C"})));
So to conclude, make a parallel between your implementation (and understand what happens at runtime)::
// does not compile
public class ArithmeticFunction implements MyFunction {
public double executeFunction(List<Integer> vector) {
int retVal = 0;
for (int i = 0; i < vector.size(); i++) {
retVal = vector.get(i) + retVal;
}
return retVal;
}
}
and the above-presented example.
Oh, and to fix your problem, you have to do::
public interface Function<T> {
public double executeFunction(List<T> vector);
}
I know that maybe some of the concepts presented here are unclear, so your best bet is to get up to speed using a tutorial on generics.
TL;DR: putting <T> on the method means that the actual type of the list will be known when the method is called. <T> on the interface means that the type of the list is known when the class is declared.
This declaration
public interface Function {
public <T> double executeFunction(List<T> vector);
}
means to something like:
The method executeFunction() can take in input a list of any type, and calculate a double from it.
Who calls this method can legally pass you List<Double>, List<Integer>, List<String> and so on. This is probably not what you want.
If you change the interface declaration like this:
public interface Function<T> {
public double executeFunction(List<T> vector);
}
you can declare your class in this way:
public class Summation implements Function<Double> {
public double executeFunction(List<Double> vector) {
// ...
}
}
Now you are sure that every element in vector is a Double, so you can safely sum them up.
public interface Function<T> {
public T executeFunction(List<T> vector);
}
Read as:
public interface Function with type T
That is why the function executeFunction returns that type T you declared above.
Note that T is always an Object, but Java can handle primitive types (int, double) through automatic boxing.