I am making a generic class that utilizes T as the main parameters. I need to sort some Ts, but to do that, I need to implement a generic compareTo. I've been looking all over to find out how to do this. I know how to implement something like
public class Foo implements Comparable {
private int age;
public Foo (int age) {
this.age = age;
}
public int compareTo(Foo a) {
if (age < a.age) {
return -1;
}
if (age == a.age) {
return 0;
}
if (age > a.age) {
return 1;
} else {
return 0;
}
}
}
but I'm lost when I'm trying to compare two generic objects (e.g., if T is Integer, it compares Integers, if T is String, it compares String). Basically, this:
T.compareTo(T)
I know it's probably an easy solution that I'm overlooking, but I don't understand because there is no variable I can compare.
Use the generic form of Comparable with a generic type parameter, instead of the raw form of Comparable that has none. It makes sense to compare Foo objects with other Foo objects. I wouldn't use a generic type parameter; I would just supply Foo as the type parameter on Comparable.
Try
public class Foo implements Comparable<Foo> {
Then your compareTo method should work.
If you want your class to be able to sort things of some arbitrary type T, you have two options, and you can do them both at once if you like.
public class Sorter {
public static < T extends Comparable< ? super T > >
void sort( T[] atUnsorted ) {
// here you know that the elements of atUnsorted
// can be compared with each other using their
// compareTo methods
...
}
public static < T > void sort(
T[] atUnsorted, Comparator< ? super T > cmpT
) {
// here you can use cmpT.compare to compare
// any two elements in atUnsorted
...
}
}
If you prefer having a dedicated Sorter instance for each type T you can make the type parameter into a class level generic parameter and not use static methods.
Related
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);
}
I have the following code:
public abstract class Heap {
Comparable<?> data[];
int count, size;
public Heap( int size ) {
this.size = size;
data = new Comparable<?>[ size + 1 ];
this.count = 0;
}
public abstract void insert( Comparable<?> item );
}
class MinHeap extends Heap {
public MinHeap (int size ) { super(size); }
public void insert( Comparable<?> item ) {
//this line here is giving me an error
//due to how I am storing the array in Heap
int k = data[ 0 ].compareTo( item );
}
}
The line indicated above is giving me this error: The method compareTo(capture#1-of ?) in the type Comparable<capture#1-of ?> is not applicable for the arguments (Comparable<capture#2-of ?>). I cannot figure out a way to make it work while maintaining these conditions: 1) I want the MinHeap to work with any data that implements Comparable, 2) I do NOT want to pass a pre-initialized array into the constructor. I say this because I do not want to do the following:
abstract class Heap< T extends Comparable<T> > {
T data[];
public Heap( T data[], int size ) {
this.data = data;
//I do not want to have to pass an instantiated array.
//I want the constructor to handle the instantiation. If I do this I know the issue with the
//compareTo will be solved, but I really prefer to avoid this.
}
}
My question is this: In my code, why am I getting this error? Does anyone know a way besides the way that is described in the second example? I would like to be able to create a min heap data structure with any comparable data. All helpful comments are appreciated. Thank you.
Side note: do not worry about the access modifiers of the instance variables. I left them as default for simplicity. I do know that they should be private with setters/getters or protected.
First of all, this code is invalid for creating a generic array:
data = new Comparable<?>[ size + 1 ];
This link in the Java Trails explains why it's illegal, but it boils down to the fact that arrays must know their type at compilation, and generics work based off of type erasure and can be inferred at runtime.
But before we can fix that, there's an issue with your generics - they're not really...generic. You're only using the wildcard generic here with no bounds.
If you want to have your abstract class with a generic array that is full of Comparable, then you want to have your abstract class with a bound to Comparable<T>, and have your data simply be bound to T. With this, we can finally fix the array initialization into a compilable (but unchecked cast) form:
data = (T[]) new Comparable[size + 1];
Here's the full class for reference. It's close to your second form, and doesn't require that you pass in an instantiated array. Further, since T is bound to Comparable<T>, we don't need to declare it as an argument in the method - we can simply provide T.
public abstract class Heap<T extends Comparable<T>> {
T data[];
int count, size;
public Heap(int size) {
this.size = size;
data = (T[]) new Comparable[size+1];
this.count = 0;
}
public abstract void insert(T item);
}
Further to this example, you would also want to add the generic type to your subclass as well:
class MinHeap<T extends Comparable<T>> extends Heap<T>
Try this one:
First compareTo() return int not boolean value.
public abstract void insert( Comparable<?> item ); is wrong.
Use List in case of generic instead of static array. For more info read How to create a generic array?
Sample code:
abstract class Heap<T> {
List<Comparable<T>> data;
public Heap(int size) {
data = new ArrayList<Comparable<T>>();
}
public abstract void insert(T item);
}
class MinHeap<T extends Comparable<T>> extends Heap<T> {
public MinHeap(int size) {
super(size);
}
public void insert(T item) {
int k = data.get(0).compareTo(item);
}
}
Your data can contain any kind of object, as long as its class implements Comparable. So you could have Strings, Integers, Longs, or Bananas inside your array.
And comparing an Integer with a String or with a Banana doesn't make sense. That's why the compiler doesn't let you compile this code.
The second way is the right way. You can use an array of objects internally, and cast each object to a T. If all your methods only accept instances of T, then the casts are guaranteed to succeed. Or you can use a List instead, which is much more generic-friendly than arrays.
How do I do this? Because you can only extend one class so it can only have one upper bound.
In my case I need the generic type to be bounded in String and int. If I use an Integer wrapper instead of int and rely on auto-boxing, I can make it but the problem is other classes can be passed as a type parameter as well.
What's the best way to do this?
You could use the non generic variants of collections (e.g List), or
more cleanly explicitly List<Object> to show code's intention.
Wrap that in a MyList class, and create add(), get() methods for each type you want to support:
add(Integer elem);
add(String elem);
But Object get() cannot be typed, such that it makes sense.
So finally you also can use Object with List, and omit the wrapper.
I don't think you can do it. String also is a final class and all that stuff. As #NimChimpsky said, you are probably better using Object itself. Another solution is a wrapper for both classes, but you will still have a resulting object which you will probably need to cast around and rely on instanceof:
class StringInt {
private String string;
private Integer integer;
public StringInt(String s) { this.string = s; }
public StringInt(Integer i) { this.integer = i; }
public Object getValue() { return string != null ? string : integer; }
}
Or with an ugly verification, which, obviously, will only apply at runtime...
class StringIntGen<T> {
private T t;
public StringIntGen(T t) {
if (!(t instanceof String) && !(t instanceof Integer))
throw new IllegalArgumentException(
"StringIntGen can only be Integer or String");
this.t = t;
}
public T getValue() { return t; }
}
I have created a HashMap object which stores a String as key and corresponding value as int. Now I want to have a Priority Queue which have all the String present in HashMap object with value as reference for assigning priorities. I have written the following code
public class URIQueue {
private HashMap<String,Integer> CopyQURI;
private PriorityQueue<String> QURI;
public class TComparator<String> {
public int compareTo(String s1, String s2) {
if (CopyQURI.get(s2) - CopyQURI.get(s1) >= 0) {
return 1;
} else {
return 0;
}
}
}
public URIQueue() {
CopyQURI=new HashMap<>(100);
TComparator<String> tc=new TComparator<>();
QURI=new PriorityQueue<>(100, tc); //Line x
}
}
Line x is showing error cannot infer type argument for priority queue. Please guide me what mistake I have done.
The error you are referring to states, that it cannot guess the generic type parameter which you have omitted. The reason for that is that the constructor you are using is not known. It is not known, because you second argument is not a comparator. Your comparator has to implement the java.util.Comparator interface in order to be type safe for the constructor to accept.
public class TComparator<String> implements Comparator<String> {
#Override
public int compare(String arg0, String arg1) {
// ...
}
}
Also mind, in the Comparator interface the appropriate method is called compare and not compareTo.
A general advice, I have to agree with Louis Wasserman, for two given arguments a comparator should always return the same result and not depend on the state of the application. It's just too easy not to think of some case and the application is eventually flawed.
With the type Integer you can do this:
int lowest = Integer.MIN_VALUE;
What can I do if I use generics?
K lowest = <...>;
I need this in order to implement something similar to a PriorityQueue.
I have access to a node I want to remove from the queue, but it is not the min.
1. I need to make it the min by decreasing the key of that node,
2. And then remove the min.
I am stuck on the first step. The only thing I can do is set the key of the node to the current min. Not sure it is enough.
There is no generic form of MIN_VALUE or MAX_VALUE for all Comparable types.
Think about a Time class that implements comparable. There is no MAX_VALUE for Time even though it is Comparable.
I am trying to imagine what scenario would require such behavior. This is the best I can come up with...
WARNING: This code is dangerous. Please be merciful to me for posting such an abomination. It is only a proof of concept.
public class Lowest<K> implements Comparable<K> {
public int compareTo(K other) {
return -1;
}
}
And then...
public class Test {
public <K extends Comparable<K>> K findMaximum(List<K> values) throws Exception {
K lowest = (K) new Lowest<K>(); /// XXX DANGER! Losing compile-time safety!!!
K maximum = lowest;
for (K value : values) {
if (maximum.compareTo(value) < 0) {
maximum = value;
}
}
if (maximum == lowest) {
throw new Exception("Could not find a maximum value");
} else {
return maximum;
}
}
}
This doesn't make any sense...
Given that you don't know what K is at that point, (i.e. You're implementing it generically... duh!) you can't specify a min/max bound for it.
in a case where K could be a int, long, string OR object, you couldn't sensibly guess to use
Integer.MIN_VALUE, "" OR NULL.
I guess what you're looking for is a K.MIN_VALUE_OF_EVENTUAL_TYPE but that doesn't exist.
You can make a wrapper class that "adds" a minimum and maximum value to all types. It just has two static instances that represent minimum and maximum, and then other instances wrap some other value of some type. When we do a comparison, we check if one of the things is the minimum or maximum, and return the proper result; and otherwise we just do the same comparison as the underlying type. Something like this:
class Extended<T extends Comparable<? super T>> implements Comparable<Extended<T>> {
private Extended() { }
private static Extended min = new Extended();
private static Extended max = new Extended();
#SuppressWarnings("unchecked")
public static <T extends Comparable<? super T>> Extended<T> getMin() {
return (Extended<T>)min;
}
#SuppressWarnings("unchecked")
public static <T extends Comparable<? super T>> Extended<T> getMax() {
return (Extended<T>)max;
}
public T value;
public Extended(T x) { value = x; }
public int compareTo(Extended<T> other) {
if (this == other) return 0;
else if (this == min || other == max) return -1;
else if (this == max || other == min) return 1;
else return this.value.compareTo(other.value);
}
}
Consider not making K a generic, but using an interface that wraps the primitive wrapper (a double wrapper!).
import java.util.HashMap;
public class NodeWrapper<K extends Comparable<K>> implements Comparable<NodeWrapper<K>> {
private static HashMap<Class, NodeWrapper> minVals = new HashMap<Class, NodeWrapper>();
private K value;
private NodeWrapper() {
super();
}
public NodeWrapper(K value, Class<K> clazz) {
super();
this.value = value;
if (minVals.get(clazz)==null) {
minVals.put(clazz, new NodeWrapper<K>());
}
}
public K getValue() {
return value;
}
public static NodeWrapper getMinValue(Class clazz){
return minVals.get(clazz);
}
public void setValue(K value) {
this.value = value;
}
#Override
public int compareTo(NodeWrapper<K> o) {
NodeWrapper min = minVals.get(this.getClass());
if (this==min && o==min) {
return 0;
} else if (this==min){
return -1;
} else if (o==min){
return 1;
} else {
return this.value.compareTo(o.value);
}
}
}
Briefly, the idea is that whenever a new class is instantiated, a minimum value is created and put into a static hashmap that stores the minimum values for each class. (In fact, these values are NOTHING at all, just a sentinel object, but since we will use object equality to determine if something is the min value, this is no problem at all.) All that's necessary is that the wrapped object be comparable to other instances of itself in general.
One drawback is that when you call getMinValue you will have compiler warnings, since the return type will have no generic information. There may be a more elegant way around this, but I can't think of it right now.
This general idea might be rather nice overall. However, I should really stress: this will absolutely break if you try it with any polymorphism or any mixing of mutually comparable classes. Longs and Integers in the same tree will completely destroy you.
er... what's the problem again?
PriorityQueue, like all Collections, allows you to use an instance of an object to remove it from the collection.
Uh doesn't this depend on what type K is?
The point of Generics is that K can be any type (or any subclass of a certain type); in order to be able to call methods on K or access properties of it, you need to restrict it's type bounds with wildcards.
just because an object is a comparable does not mean it has to have a minimum value. The reason int has a min value of -(2^(31)) is because you need 1 bit for a sign, so 2^31 is the largest (or smallest) possible integer that can be stored. For things like string, it does not make any sense since there is no largest/smallest possible string, it is memory bound.
You might have to create an interface "IInfinity", and have K extends IInfinity, and IInfinity to have a method "getInfinityValue()", and then wrap/extend Integer, Double, BigDecimal, etc in a class that implements IInfinity ... and ugh!
Basically you want any type K to implement some static functions say lowest and highest which obey the standard mathematical properties.
I assume that for this sense of lowest (or highest) to be usable you would want any Comparable object to have these methods. (or static fields). If you are only interested in your own custom objects, the way to do this would be to have everything inherit from an abstract data type which declared static fields for MINVALUE and MAX_VALUE and then your type varaibles would be . If you need this functionality for other classes you will need to cre4ate some sort of external hashmap which tracks these properties for different classes (but that would get pretty ugly)