3

I want to compare an array of comparables. The simplest way seems the following (details not shown):

public class ArrayComparable implements Comparable<ArrayComparable>{
ArrayList<Comparable<?>> list = new ArrayList<Comparable<?>>();

@Override
public int compareTo(ArrayComparable ac) {
    Iterator<Comparable<?>> itr = ac.list.iterator();
    for(Comparable<?> l : list) {
        Comparable<?> itrNext = itr.next();
        if(itrNext.getClass() == l.getClass()) {
            if(itrNext.compareTo(l)) {
                //something
            } else {
                //other stuff
            }
        } else {
            //some other thing
        }
    }
}

Of course the problem here is that the compareTo as in itrNext.compareTo(l) will not work giving the error: The method compareTo(capture#6-of ?) in the type Comparable<capture#6-of ?> is not applicable for the arguments (Comparable<capture#7-of ?>) which I understand why (as far as the method is concerned I might be comparing apples to oranges). On the other hand, I know I am not as I check for the class of things before comparing them.

So is there a way I can make this work? Don't worry about the sanity of comparing arrays of any comparables, as I have a good reason why I want to do that.

EDIT- SO why would I want to do something like this. Say I wanted to have an array of comparables, and I didn't care what was contained in each index, as long as the types corresponded, and they could be compared. Then I could do a general lexicographical compare between these arrays. This way I don't have to write a comparable for (int,int) and (int, string), and (string, double, string) or whatever you need. I just write one, and as long as I make sure that the types match (and I can), I am good to go.

delmet
  • 1,013
  • 2
  • 9
  • 23
  • "On the other hand, I know I am not as I check for the class of things before comparing them." So? Just because two objects are the same class doesn't mean you can compare them. – newacct Mar 08 '13 at 07:12

5 Answers5

3

Make ArrayComparable a generic class so that you can properly parameterize the generics rather than using <?> everywhere. Oh, and you might as well implement Iterable as well.

public class ArrayComparable<T> implements Comparable<ArrayComparable<T>>, Iterable<T>
{
    List<Comparable<T>> list = new ArrayList<Comparable<T>>();

    @Override
    public int compareTo(ArrayComparable<T> ac)
    {
        // snip
    }

    @Override
    public Iterator<T> iterator()
    {
        return list.iterator();
    }
}
Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • 1
    I think this class (and the `List` by extension) contains `Comparable`s of any type, not just a specific type `T`. – ColinD Apr 22 '11 at 18:44
  • 2
    i suspect the OP wants the array to contain different comparables, not just of one type (i.e. he is crazy but he knows it) – Claudiu Apr 22 '11 at 18:46
  • If that's the case, then _ew_. ...oh hey, Claudiu! – Matt Ball Apr 22 '11 at 18:46
  • Yes, I am fully aware of my insanity. But there are applications where one needs this sort of a thing. This particular one comes from hadoop. – delmet Apr 22 '11 at 19:18
  • 2
    You should restrict `>` to make sure that `T` is comparable to itself – newacct Apr 22 '11 at 20:33
3

Using the raw type Comparable wherever you're currently using Comparable<?> should work. Actually, you could just do that in one place if you want:

if (((Comparable) itrNext).compareTo(l) == 0)
ColinD
  • 108,630
  • 30
  • 201
  • 202
  • Shedding the template does indeed work. It is too bad I need to live with warnings. What I wanted was not that unreasonable. But I guess this is going to be the way to go. – delmet Apr 22 '11 at 23:02
  • @delmet: Add an `@SuppressWarnings("unchecked")` to the method with a comment explaining why it should be safe that you're doing this. – ColinD Apr 22 '11 at 23:09
0
public class GenericDemo<T>{
  T g;
 public <T extends Comparable<T>> void printData(T a[]){
    T max = a[0];
    if(a[1].compareTo(max)>0){
        max=a[1];
    }
    if(a[2].compareTo(max)>0){
    max=a[1];
    }
    System.out.println(max);
    System.out.println("DataType: " +a.getClass().getName());

      }
    public static void main(String[] ar)
    {
     Integer a[]={1,2,3};
     Byte b[]= {4,6,7};
     Short c[]={6,8,9};

     GenericDemo g = new GenericDemo();
     g.printData(a);
     g.printData(b);
     g.printData(c);
     } 
}
upasna
  • 1
0

A good answer to this would be:

public final class ArrayComparable<T extends Comparable<T>>
    implements Comparable<ArrayComparable<T>> {

    private final ArrayList<T> list = new ArrayList<>();

    @Override
    public int compareTo(final ArrayComparable<T> other) {

        final Iterator<T> it = other.list.iterator();

        for (final T element : list) {
            final T otherElement = it.next();

            final int comparison = element.compareTo(otherElement);
            if (comparison < 0) {
                // something
            } else if (comparison > 0) {
                // other stuff
            } else {
                // other stuff
            }
        }
        return 0;
    }
}
Aither
  • 1
  • 1
0

Try this:

    if(itrNext.getClass().cast(itrNext).compareTo(l.getClass().cast(l))) {
        //something
    } else {
        //other stuff
    }
Claudiu
  • 224,032
  • 165
  • 485
  • 680