Comparing different type of Objects with comparabl

2019-03-05 05:25发布

问题:

A.java

public class A implements Comparable {
    private String id;
    private String name;

    public A(String a, String b) {
        id = a;
        name = b;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int compareTo(Object o) {
        A a = (A) o;
        return id.compareTo(a.getId());
    }
}

B.java

public class B implements Comparable {
    private String b_id;
    private String other;

    public B(String a, String b) {
        b_id = a;
        other = b;
    }

    public String getBId() {
        return b_id;
    }

    public void setBId(String id) {
        this.b_id = id;
    }

    public String getOther() {
        return other;
    }

    public void setOther(String other) {
        this.other = other;
    }

    public int compareTo(Object o) {
        B b = (B) o;
        return b_id.compareTo(b.getId());
    }
}

Learn.java

public class Learn {

    public static void main(String[] args) {

        List<A> listA = new ArrayList<A>();
        List<B> listB = new ArrayList<B>();
        List<Object> listAll = new ArrayList<Object>();
        listA.add(new A("aa", "bb"));
        listA.add(new A("ae", "bbn"));
        listA.add(new A("dfr", "GSDS"));
        listB.add(new B("nm", "re"));
        listB.add(new B("asd", "asfa"));

        listAll.addAll(listA);
        listAll.addAll(listB);
        Collections.sort(listAll);
        for (Object o : listAll) {
            if (o instanceof A)
                System.out.println(o.getId);
            else if (o instanceof B)
                Syatem.out.println(o.getBId);
        }

    }

}

The error i get is at the line Collections.sort(listAll); It says.

Bound mismatch: The generic method sort(List<T>) of type Collections is not applicable
for the arguments (List<Object>). The inferred type Object is not a valid substitute
for the bounded parameter <T extends Comparable<? super T>>

What to do? Also is the rest of the logic all right?

What i am trying to do is have a list of A and list of B with one attribute same as id; though the variable name is not the same. i.e id in A and bid in B. Now i put both the lists in ListAll and do sort on them on the same variable id/bid. I have A and B implementing Comparable.

and my listAll is of type Object?

how do I do it? thanks.

回答1:

You could add a common base class and implement comparison there, as in:

abstract class AandBComparable implements Comparable {

  public int compareTo(Object o) {
    AandBComparable ab = (AandBComparable) o;
    return getId().compareTo(ab.getId());
  }

  public abstract String getId();
}


回答2:

To be able to sort a list, its elements must be comparable to each other. That's not the case here. Instances of A can only be compared with other instances of A. Same for B.

If you want to sort a list containg A and B instances, you need to provide Comparator which will happily take two As, two Bs or an A and a B, and compare these objects as you want them compared.

public class AOrBComparator implements Comparator<Object> {
    @Override
    public int compare(Object o1, Object o2) {
        String o1Id = getId(o1);
        String o2Id = getId(o2);
        return o1Id.compareTo(o2Id);
    }

    private String getId(Object o) {
        if (o instanceof A) {
            return ((A) o).getId();
        }
        else if (o instanceof B) {
            return ((B) o).getId();
        }
        else {
            throw new IllegalArgumentException("Can only get ID from A or B");
        }
    }
}

But maybe A and B should implement the same Identifiable interface, and the list should be a List<Identifiable>. This way, you could easily write a comparator that compares two instances of Identifiable, and it would work whether the actual instance is A, B, or any other Identifiable.



回答3:

I do not believe the exception raises where you tell, but rather in a call to sort()

Anyway, it means something like

"The sort method expects a List of elements that implement comparable. But you tell him that you are giving a list of Object, and not all Object implement Comparable. So, the compiler cannot be sure that at realtime the objects passed in the list will implement Comparable (as required), and throws an error"

The solution? Define the list with a bound class that implements Comparable

 List<A> listAll = new ArrayList<A>(); 

Update: To have all items in the same list then either:

a) Have all items derive from a common class / interface that implements Comparable. Usually this would be the most Object Oriented Programming friendly approach, since if you want to compare both classes they must be somehow related. Either extend B from A, A from B, A and B from another class, or make A and B implement another interface (which itself implements Comparable).

b) As JBNizet said, use a Comparator.

Again, I strongly recommend using the a solution.



回答4:

You need a base (dummy) class which will implement Comparable and let A and B derive from class. Something like:

public abstract class MyComparableClass implements Comparable {
}

public class A extends MyComparableClass {
... // implementation of compareTo
}

public class B extends MyComparableClass {
...// implementation of compareTo
}

In your main program then simply define the Collection to be:

List<MyComparableClass> listAll = new ArrayList<MyComparableClass>();