Using Comparable to Compare Generic Variables

Using Comparable to compare generic variables

Option 1.Use a Comparator

public class Cmp<K extends Comparable<K>, V> implements Comparator<Pair<K, V>> {
@Override
public int compare(Pair<K, V> o1, Pair<K, V> o2) {
return o1.k.compareTo(o2.k);
}
}

public class Utils {
public static <K extends Comparable<K>, V> Collection<Pair<K, V>> sortPairCollection(
Collection<Pair<K, V>> col) {
ArrayList<Pair<K, V>> list = new ArrayList<>();
Collections.sort(list, new Cmp<>());
return list;
}
}

Option 2.
Implement Comparable

public class Pair<K extends Comparable<K>, V> implements Comparable<Pair<K, V>> {
private K k;
private V v;
@Override
public int compareTo(Pair<K, V> o) {
return k.compareTo(o.k);
}
}
public class Utils {
public static <K extends Comparable<K>, V> Collection<Pair<K, V>> sortPairCollection(Collection<Pair<K, V>> col) {
ArrayList<Pair<K, V>> list = new ArrayList<>();
Collections.sort(list);
return list;
}
}

Or just

public class Utils {
public static <K extends Comparable<K>, V> Collection<Pair<K, V>> sortPairCollection(Collection<Pair<K, V>> col) {
ArrayList<Pair<K, V>> list = new ArrayList<>();
Collections.sort(list, (p, o) -> p.k.compareTo(o.k));
return list;
}
}

You don't have do create an instance for your static method btw. just invoke

Utils.sortPairCollection(list);

Compare generic types from a collection to the same type java

but if I type <E extends Comparable> in my Box.count method then i cant pass the arguments.

The reason why you can't pass the arguments is because Box does not implement Comparable.

What you should do instead is add the generic constraint in the Box class:

class Box<T extends Comparable<T>> { ... }

Also, your count method is a bit too generic. It will probably make more sense if compeer's type is changed to Box<T> and list to List<Box<T>>.

The method signature now looks like this:

public static <T extends Comparable<T>> int count(List<Box<T>> list, Box<T> compeer) {

And you can implement the method like this:

return (int)list.stream().
filter(x -> x.name.compareTo(compeer.name) < 0).count();

Comparing generic types using Comparable and Comparator

Thanks to the combined efforts of Chrylis, Catalin Pol, and Louis Wasserman, I learned I needed to correct my class to:

public class SortedValueStore<K, V extends Comparable<? super V>> implements PairStore187<K, V>, Iterable<K>, {

I no longer needed to write my own compareTo() method.

This did the trick. I'm relatively new to java so it took me a while to get what everyone was saying, but everyone was persistent with their efforts. Thanks to all for the help!

Java how to compare two generic type parameters

The < and > operators can only be used with primitive types, and the Number class does not implement Comparable itself, so you can't use compareTo.

However if you add Comparable<T> as a type bound:

public class MyList<T extends Number & Comparable<T>> {
...
}

then you can use the compareTo method:

public T largest() {
boolean onFirstObj = true;
T largestVal = null;

for (T t : list) {
if (onFirstObj) {
largestVal = t;
onFirstObj = false;
} else {
if (t.compareTo(largestVal) > 0) {
largestVal = t;
}
}
}

return largestVal;
}

compareTo() with generic type

Comparable<?> means that you don't know what kind of Comparable you're getting; you could be getting Comparable<Object>, which doesn't work unless you explicitly override compareTo for that instance of Object.

The correct solution to this is to introduce a type parameter to the method such that the type you care about is bound to Comparable.

private <T extends Comparable<T>> int compare(T[] arr, T item) {
return arr[0].compareTo(item);
}

The above will still work with a Comparable[], not a Comparable<?>[]. Generics and arrays don't mix very well, so where you can, try to avoid combining the two.

If you want to avoid the unchecked warnings (which at this point can be safely ignored due to array covariance),then you would modify the signature of your methodArr method to accept a similar bound.

<T extends Comparable<T>> void methodArr(final T[] arr, T item) {
// use the passed-in arr and item variables instead.
}

Implementing Comparable with a generic class

Item (without any type argument) is a raw type, so:

  1. We could pass any kind of Item to Item.compareTo. For example, this would compile:

    new Item<String>().compareTo(new Item<Integer>())
  2. The method o.getT() returns Comparable instead of T, which causes the compilation error.

    In the example under the 1st point, after passing Item<Integer> to Item.compareTo, we would then erroneously pass an Integer to String.compareTo. The compilation error prevents us from writing the code which does that.

I think you just need to remove the raw types:

public class Item<T extends Comparable<T>>
implements Comparable<Item<T>> {

...

@Override
public int compareTo(Item<T> o) {
return getT().compareTo(o.getT());
}
}

Comparing Generics that are comparable in Java

I know the data value will be a object-wrapped primitive or a String, so they are comparable.

Then you can tell the compiler about it:

public class TreeNode<T extends Comparable<T>>

If you do that, you will get access to the compareTo method defined in Comparable.

How to compare Strings & ints in Generic Using comparable C#

You have to specify that T can be compared, the compiler can't know otherwise that type to expect. This way you can use CompareTo for both your conditions:

public class QuickSort
{
public static int Partition<T>(T[] arr, int lo, int hi) where T : IComparable
{
int i = lo + 1;
int j = hi;
while (j > i)
{
while (arr[i].CompareTo(arr[lo]) == 0)
i++;
while (arr[j].CompareTo(arr[lo]) > 0) // means arr[j] > arr[lo]
j--;

Swap(ref arr[i], ref arr[j]);
}

Swap(ref arr[lo], ref arr[j]);

return j;
}
}

Also, I don't think you want to compare different QuickSort instances, so I removed its interface.

Update: Based on Hawkmooon's comment, I took a second look at your method and thought its signature can be even simpler:

    public static int Partition(IComparable[] arr, int lo, int hi)
{
int i = lo + 1;
int j = hi;
while (j > i)
{
while (arr[i].CompareTo(arr[lo]) == 0)
i++;
while (arr[j].CompareTo(arr[lo]) > 0)
j--;

Swap(ref arr[i], ref arr[j]);
}

Swap(ref arr[lo], ref arr[j]);

return j;
}

I think your code may be missing something. Just in case, here you have a full C# example of a working quicksort method.

Create a compareTo to a Generic Class that Implements Comparable

so to summarize the said above and to puzzle it together into a working code this is:

    public class DoubleKey<K extends Comparable<K>, J extends Comparable<J>>
implements Comparable<DoubleKey<K, J>> {

private K key1;
private J key2;

public DoubleKey(K key1, J key2) {
this.key1 = key1;
this.key2 = key2;
}

public K getFirstKey() {
return this.key1;
}

public J getSecondKey() {
return this.key2;
}

public int compareTo(DoubleKey<K, J> that) {

int cmp = this.getFirstKey().compareTo(that.getFirstKey());
if (cmp == 0)
cmp = this.getSecondKey().compareTo(that.getSecondKey());
return cmp;
}
}


Related Topics



Leave a reply



Submit