I want to define a generic class ComparableList<> that extend ArrayList and implements Comparable interfaces, such that two objects of type ComparableList can be compared using the compareTo method. The compareTo should perform a lexicographic comparison.
Here's my code:
class ComparableList <T extends Comparable<T>> extends ArrayList implements Comparable<ComparableList>{
#Override
public int compareTo(ComparableList o){
Iterator citer = this.iterator();
Iterator oiter = o.iterator();
while (citer.hasNext() && oiter.hasNext()){
if (citer.next() > oiter.next()){
return 1;
}else if (citer.next() < oiter.next()){
return -1;
}else {
if (!citer.hasNext()){
return -1;
}
if(!oiter.hasNext()){
return 1;
}
}
}
return 0;
}
}
and I got error messages like this:
TCL.java:11: error: bad operand types for binary operator '>'
if (citer.next() > oiter.next()){
^
first type: Object
second type: Object
TCL.java:13: error: bad operand types for binary operator '<'
}else if (citer.next() < oiter.next()){
^
first type: Object
second type: Object
I thought it should be a ComparableList but not an Object. Can anyone tell me the reason?
You need to compare the objects using Comparable.comapreTo() (that's why you have <T extends Comparable<T> there). You need to first check for nulls on either side.
Also, each call to Iterator.next() iterates to next element, you don't want to call it twice in one loop iteration - store the items at the loop start then use the stored values.
Comparable doesn't override the > and < operators (nothing can). Since your T implements Comparable, use compareTo:
int result = citer.next().compareTo(oiter.next());
if (result != 0) {
return result;
} else {
if (citer.hasNext()) {
return -1;
}
if (oiter.hasNext()) {
return 1;
}
}
Note that that also calls next only once per iteration, since next advanced the iterator.
Each element in your ComparableList is of type T extends Comparable<T>, for sure the binary operator is not available for it (Java doesn't have operator overloading), but since it extends Comparable, you have compareTo to be used as replacement for < and >. Use it instead.
Related
public void sort(){
//TO DO
int k = start;
int temp = 0;
for(int i=0; i<size-1; i++){
for(int j=0; j<size-1; j++){
if((cir[(k % cir.length)]) > cir[((k+1) % cir.length)]){
temp = cir[(k % cir.length)];
cir[k%cir.length] = cir[(k+1)%cir.length];
cir[(k+1)%cir.length] = temp;
}
k = (k+1)%cir.length;
}
}
}
//Here the cir[] type is object. but why this problem is occurring?
The operators <,> are not defined for Object.
How would you compare them?
Define a method for the class of the object you are using. Say greaterThan(YourObjectType otherobject). Then implement it according to how you want to compare. That depends on YourObjectType.
Edit.
Implement the Comparable interface as added in a comment.
The others have already mentioned it but I will reiterate: if you want to write some generic sort method you'd want to either provide a Comparator or have the elements implement Comparable.
With generics your methods could look like this:
public <T extends Comparable<T>> void sort(T[] array) { ... }
public <T> void sort(T[] array, Comparator<T> comparator) { ... }
Both variants require the user to provide some code that defines how <, == and > are defined for the objects in question (the methods Comparable.compareTo(right) or Comparator.compare(left, right) return a negative (normally -1) int, 0 or a positive int (normally 1) to indicate <, == or >).
In general, you'd use Comparable if you can define a natural (default) ordering, e.g. if you'd work with an array of people they normally might be ordered by name.
Comparator on the other hand is more flexible and normally used if you can't or don't want to use a default order. In that case you'd provide a comparator for each case, e.g. when you'd want to sort cars either by price or speed you'd provide a comparator that internally either compares prices or speed.
Note that this doesn't work for primitives like int etc. Thus you'd either have to convert them to their wrapper classes, e.g. Integer or provide custom methods that make use of the "normal" operators.
In the following code, the method isSorted causes my static code analyzer to give me a warning saying:
Unchecked call to 'compareTo(T)' as a member of raw type 'java.lang.comparable'
Now, I found from other posts that the solution is to generify the function as done in the equivalent function isSortedG.
However, I do not understand why the second method is better than the first. As far as I can tell, since isSorted takes a Comparable[] as argument, this should result in a compile time check of any usage of that function to make sure that the input array is indeed of a type that implements Comparable.
In other words, what is this 'Unchecked call' that the static checker is warning about?
public class SortChecker{
public boolean isSorted(Comparable[] arr){
if(arr.length == 1){
return true;
}
for(int i = 1; i < arr.length; ++i){
if(arr[i].compareTo(arr[i-1]) < 0){
return false;
}
}
return true;
}
public <T extends Comparable<? super T>> boolean isSortedG(T[] arr){
if(arr.length == 1){
return true;
}
for(int i = 1; i < arr.length; ++i){
if(arr[i].compareTo(arr[i-1]) < 0){
return false;
}
}
return true;
}
}
A nongeneric Comparable "can" be compared to any Object (as per its compareTo() signature), but in actuality, there may only be a small set of types to which it can be meaningfully compared (and giving it other types will cause compareTo() to throw an exception). For example, you can cast an Integer to a Comparable, but that still won't let you compare it to a String. Therefore, a Comparable[] is risky business, because you have no idea which elements are safe to compare and which are not. The generic version is safer because a Comparable<T> usually is comparable to any T, and if T is constrained to implementors of Comparable<? super T>, all elements of a T[] should be mutually comparable.
I want to generate a binary tree with key - value pairs in their nodes.
In my binary tree I want to implement nodes at the beginning with an insert method, which implements a new left node if the key is smaller than the key of the current node. Then if there is already a left node it will check again for it. The same logic follows for right/greater node inserts.
I wrote my code first using the int type because it's way easier for me to test my code before I use generics (new topic for me). It worked when using int but I an unsure how to compare two generics with themselves by using "<" or ">".
public ListCell<Type> checkKey(Type key, ListCell<Type> checkCell) {
ListCell<Type> newCell = null;
if (key < checkCell.key && checkCell.left != null) {
...
}
...
}
I don't know if it's worth saying but I'm creating my binary tree with a selfcoded list.
Above you can see my current checks but i can't compare my given key now with checkCell.key because of them not being numbers.
So my general question is how to compare the keys in generics if they are "smaller" or "greater" than the other for my implementation in a binary tree.
Thanks in advance
You would need to ensure that your generic type implemented the Comparable interface, and then use the compareTo method instead. Java does not support overloading the > operator (or any operator overloading, for that matter).
As per the documents, compareTo:
Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
An example (that you'll have to map on to your exact code), assuming that key is your item you will store in your node, and checkCell.key is your node
int compareResult = key.compareTo(checkCell.key);
if (key < 0) { // it goes on the left }
else if (key == 0) { // it is the same }
else { // it goes on the right }
In your compareTo method you need to decide what fields in your class determine it's "ordering". For example, if you have a size and priority field, you might do:
#Override public int compareTo(Type other) {
final int BEFORE = -1;
final int EQUAL = 0;
final int AFTER = 1;
if (this == other) return EQUAL;
if (this.size < other.size) return BEFORE;
else if (this.size > other.size) return AFTER;
else { // size is equal, so test priority
if (this.priority < other.priority) return BEFORE;
else if (this.priority > other.priority) return AFTER;
}
return EQUAL;
}
Bounded type parameters are key to the implementation of generic algorithms. Consider the following method that counts the number of elements in an array T[] that are greater than a specified element elem.
public static <T> int countGreaterThan(T[] anArray, T elem) {
int count = 0;
for (T e : anArray)
if (e > elem) // compiler error
++count;
return count;
}
The implementation of the method is straightforward, but it does not compile because the greater than operator (>) applies only to primitive types such as short, int, double, long, float, byte, and char. You cannot use the > operator to compare objects. To fix the problem, use a type parameter bounded by the Comparable<T> interface:
public interface Comparable<T> {
public int compareTo(T o);
}
The resulting code will be:
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;
}
bounded type parameters
I'm doing an assignment that requires me to implement skip lists and binary search trees. I'm also supposed to implement iterators for each data structure.
The skip list and binary search tree is implemented using generics K and V.
public class SkiplistMap<K extends Comparable<K>,V> implements SortedMap<K,V>
public class SkiplistMapNode<K extends Comparable<K>,V>
public class BSTMap<K extends Comparable<K>,V> implements SortedMap<K,V>
public class BSTMapNode<K extends Comparable<K>,V>
The iterators only use the comparable type, so I plugged in ? as the non comparable type.
public class SkiplistMapIterator<T extends Comparable<T>> implements Iterator<T> {
SkiplistMap<T,?> list;
Queue<SkiplistMapNode<T,?>> queue;
int version;
public SkiplistMapIterator(SkiplistMap<T,?> sl){
list = sl;
queue = new LinkedList<SkiplistMapNode<T,?>>();
SkiplistMapNode<T,?> N = sl.getHead();
while (N != null){
queue.add(N);
N = N.getNext()[0];
}
version = sl.getVersion();
}
public void remove() throws UnsupportedOperationException{
if (queue.isEmpty()) throw new UnsupportedOperationException("No element present");
else {
T toRemove = queue.remove().getKey();
SkiplistMapNode<T,?> N = list.getHead();
while (N != null){
if (N.getNext()[0].getKey().compareTo(toRemove) == 0){
SkiplistMapNode<T,?> found = N.getNext()[0];
for (int l = list.getLevel()-1; l >= 0; l--){
N.getNext()[l] = N.getNext()[l].getNext()[l];
found.getNext()[l] = null;
}
list.incVersion();
break;
}
N = N.getNext()[0];
}
}
}
}
My problem: correctness of the code aside, when I try to make two SkiplistMap or SkiplistMapNode objects point to each other, Eclipse freaks out screaming there's a type mismatch. It tells me
Type mismatch: cannot convert from SkiplistMapNode<T,capture#16-of ?> to SkiplistMapNode<T,capture#15-of ?>
But I'm typing in the same question mark, so I'm not sure why Eclipse hates it. Can anyone explain it in dummy terms? I've tried "typing" the method but it's giving me even more errors.
1. It's not guaranteed that two ? wildcards are the same type. If it was, the ? would be a nonsense, because that's why they are: for representing an unknown type.
2. Look at the types that should be converted. 'Capture#15 of ...' and 'Capture#16 of ...' seem to be two different things.
How many question marks do you think there are in java?
Every occurrence represents an unknown type, so the compiler has to assume they are all different.
Give your "don't care" type a name, even if it has no constraints.
I have a class with two integer members. These members are block and offset numbers. I need to compare two instances of this class with great or less signs. For example;
instance1 < instance2
statement needs to return true if
instance1.blockNumber < instance2.blockNumber;
or
instance1.blockNumber = instance2.blockNumber;
instance1.offset < instance2.offset;
As far as I know Java doesn't support operator overloading. How can I do this such comparison?
Have the class implement the Comparable interface, which gives the compareTo method. You can then use the value of the number (-1 for less, 1 for more, 0 for equals) in your if statements.
If you want to put these objects in lists (say, for sorting) you should also #Override the .equals method.
import java.util.Comparable;
public class BlockOffset implements Comparable<BlockOffset>
{
private int blockNumber;
private int offset;
#Override
public int compareTo(BlockOffset instance2) {
if (this.blockNumber < instance2.blockNumber) return -1;
if (this.blockNumber > instance2.blockNumber) return 1;
if (this.offset < instance2.offset) return -1;
if (this.offset > instance2.offset) return 1;
return 0;
}
}
If the class type is your own code than you can have it implement Comparable and define the compareTo method where you can write the logic. Then, you can compare them using compareTo.
you can implement and use comparable or comparator