How to make my own generic structure to have dynamic comparator - java

I want to know how i can override compareTo method in class which implements Comparable
my structure Tree is declared like this
public class Tree<T extends Comparable<T>>
and class which used that structure is Plane that looks like that
public class Plane implements Comparable<Plane>
with override compareTo method,
the thing is if i want create a tree with default comparator i can do that easily with this
Tree<Plane> planes = new Tree<Plane>();
but i want have another tree structure with planes and with different compareTo method, how i can override that method in plane?
Thanks

Define an overloaded constructor:
public Tree() {
this(Comparator.naturalOrder());
}
public Tree(Comparator<? super T> comparator) {
this.comparator = comparator; // store in a field
}
And then use the comparator instead of the compareTo method on the tree elements.
But note that the ability to supply a comparator removes the restriction that T extends Comparable<T> (which is better as T extends Comparable<? super T> anyway).
But in such a case, you can't have a default constructor type-safely. You would either need to require a comparator always to be passed; or provide a static factory method to create a naturally-ordered tree:
static <T extends Comparable<? super T>> Tree<T> withNaturalOrder() {
return new Tree<>(Comparator.naturalOrder());
}
And invoke like
Tree<String> tree = Tree.withNaturalOrder();

you could make the comparator as a parameter of Plane
public class Plane implements Comparable<Plane> {
private Comparable<Plane> c;
public Plane(Comparable<Plane> c) {
this.c = c;
}
#Override
public int compareTo(Plane another) {
return c.compareTo(another);
}
}
whenever you want to change the compare method,just pass a diffferent Comparable instance or a lambda expression to the constructor

Related

Passing Comparator to super constructor

I need to implement my own generic binary heap in java using an arraylist. It needs to support max heaps and min heaps. This should be implemented by passing a Comparator to the BinaryHeap constructor.
So I guess depending on what the compare-method in the passed Comparator does, it's either a min or a max heap. I thought I'd make a regular PQ (which is default min) and then write a MaxPQ class that extends PQ and pass a Comparator to the super constructor. But I need to call the super in the first line, so I don't know where to initialize the Comparator. Any ideas?
Here's the code for the MaxHeap:
import java.util.Comparator;
public class MaxHeap<Bid> extends BinaryHeap<Bid> {
public MaxHeap(){
MaxComp maxComp = new MaxComp();
super(maxComp);
}
}
class MaxComp implements Comparator<Bid>{
public int compare(Bid a, Bid b){
return (a.val - b.val);
}
}
Tried Dmitrys advice super(new MaxComp());, which produced "BinaryHeap<Bid>(MaxComp) is undefined". This is the super constructor which takes a Comparator:
public class BinaryHeap<E>{
private Comparator<? super E> comp;
private ArrayList<E> array;
private int last; // index of last element
public BinaryHeap(Comparator<? super E> comp){
this.comp = comp;
array = new ArrayList<E>();
}
Just initialize it like follows:
super(new MaxComp());
Also, instead of MaxHeap<Bid> extends ... use MaxHeap extends ..., because you already specified with which type you're working with extends BinaryHeap<Bid>. That's why you can't call super constructor with your Comparator. Reason is that generic type Bid in class MaxHeap<Bid> is used instead of actual class Bid.

converting Comparable from and to Comparator?

I often have a Comparator type while I need a Comparable and the other way around. Is there a reusable JDK API to convert from one another? Something along the lines of:
public static <C> Comparable<C> toComparable(final Comparator<C> comparator) {
// does not compile because Hidden can not extend C,
// but just to illustrate the idea
final class Hidden extends C implements Comparable<C> {
#Override
public int compareTo(C another) {
return comparator.compare((C) this, another);
}
};
return new Hidden();
}
public static <C extends Comparable<C>> Comparator<C> toComparator(final Class<C> comparableClass) {
return new Comparator<C>() {
#Override
public int compare(C first, C second) {
assert comparableClass.equals(first.getClass());
assert comparableClass.equals(second.getClass());
return first.compareTo(second);
}
};
}
ComparableComparator from Apache Commons Collections seems to address Comparable<T> to Comparator problem (unfortunately its not generic type-friendly).
The reverse operation is not quite possible because the Comparator<T> represents algorithm while Comparable<T> represents actual data. You will need composition of some sort. Quick and dirty solution:
class ComparableFromComparator<T> implements Comparable<T> {
private final Comparator<T> comparator;
private final T instance;
public ComparableFromComparator(Comparator<T> comparator, T instance) {
this.comparator = comparator;
this.instance = instance;
}
#Override
public int compareTo(T o) {
return comparator.compare(instance, o);
}
public T getInstance() {
return instance;
}
}
Say you have class Foo that is not Comparable<Foo> but you have Comparator<Foo>. You use it like this:
Comparable<Foo> comparable = new ComparableFromComparator<Foo>(foo, comparator);
As you can see (especially without mixins) it's pretty ugly (and I'm not even sure if it'll work...) Also notice that comparable doesn't extend Foo, you have to call .getInstance() instead.
Since Java 8 the Comparator interface has had a few utility default methods added that assist with deriving a comparator from a comparable.
Consider the following example of sorting users by first name.
class Person {
String firstName;
String lastName;
}
List<Person> people = ...
people.sort(Comparator.comparing(Person::firstName));
You can obtain an instance of Comparator able to compare instance of Comparable type simply with
java.util.Comparator.naturalOrder()
see Comparator.naturalOrder()
this is a sort of conversion from Comparable to Comparator
Comparable items can be sorted as they have a compareTo:
Collection<Comparable> items;
Collections.sort(items);
If items are not Comparable, they need a Comparator object to do the comparison:
Collections<T> items;
Collections.sort(items, comparator);
A bridging Comparator is trivial, and you did it already.
Wrapping every T item with some Comparable adapter having a Comparator, seems useless.
First of all not inheritance but as field one needs to wrap the item.
public class CatorComparable<T> implements Comparable<CatorComparable<T>> {
public T value;
private Comparator<T> cator;
public CatorComparable(T value, Comparator<T> cator) {
this.value = value;
this.cator = cator;
}
#Override
public int compareTo(CatorComparable<T> other) {
return cator.compareTo(value, other.value);
}
}
Too much overhead.
I don't think you can really convert between them, nor does it really make sense to, since Comarable is a property of the class itself, while Comparator is an external class.
The best bet would be to write some sort of utility class that contains the underlying comparison logic (and probably have that implement Comparator), then use that class as a part of the logic for the Comparable implementation on the class itself.

Sort a list of generic interface

Here is the case, I have two classes A, B, and a generic interface C
Class A implements Comparable<A> {...}
interface C<T> {...}
//this class is not longer generic type, I do not know if this matter.
Class B extends A implements C<A> {...}
Then, at other class, I got a B List and sort it as follow
List<B> list = new ArrayList<B>();
Collections.sort(list);
This works perfectly, but now I would like to change the list of B to the generic interface C, so that it can be more general.
List<C<A>> list = new ArrayList<C<A>>();
Collections.sort(list);
This time I got the Error as follow:
Bound mismatch: The generic method sort(List<T>) of type Collections is not
applicable for the arguments (List<C<A>>). The inferred type C<A> is not a
valid substitute for the bounded parameter <T extends Comparable<? super T>>
I have tried the following modifications (of course does not work):
change C to interface C<T> extends Comparable<T>{...}
change B to class B extends A implements C<A>, Comparable<T> {...}
Can anybody help me?
change C to interface C extends Comparable{...}
Class B extends A implements C {...}
As you would have already seen from the error messages, these two won't work together as there will be a conflict in B's definition w.r.t to Comparable<A> and Comparable<C<A>>.
Since A is already implementing Comparable<A>, you can achieve the following
List<C<A>> list = new ArrayList<C<A>>();
Collections.sort(list);
by defining a Comparator for C<A> as follows:
class CTComparator<T> implements Comparator<C<T>>
{
#Override
public int compare(C<T> o1, C<T> o2)
{
return 0;
}
}
and then applying the sort method with this comparator:
List<C<T>> list = new ArrayList<C<T>>();
Collections.sort(list, comparator);
Since C<A> is not having the visibility of the Comparator defined in A hence it's complaining. Define a new comparator of C<A> as blow, it should be fine then.
List<C<A>> list = new ArrayList<C<A>>();
Collections.sort(list, new Comparator<C<A>>() {
#Override
public int compare(C<A> o1, C<A> o2) {
//implement the comarison
return 0;
}
});
If you expect C<T> to be generically comparable based on the type it contains, you should make it comparable on itself (C<T>, not T), but bound its value type to those that implement Comparable. Something like this:
public class C<T extends Comparable<? super T>> extends Comparable<C<T>> {
private final T value;
#Override
public int compareTo(C<T> that) {
return this.value.compareTo(that.value);
}
}
This only makes sense for some containers, such as those that simply wrap a value.

What does this Method mean?

Comparator<? super E> comparator()
This method is declared in the Sorted Set interface.
What does the super mean?
How is the above method different from a Generic Method, and a method with Wildcard arguments.
This means that the type of comparison can be a supertype of the current type.
Eg. you can have the following:
static class A {
}
static class B extends A {
}
public static void main(String[] args) {
Comparator<A> comparator = new Comparator<A>() {
public int compare(A a1, A b2) {
return 0;
}
};
// TreeSet.TreeSet<B>(Comparator<? super B> c)
SortedSet<B> set = new TreeSet<B>(comparator);
// Comparator<? super B> comparator()
set.comparator();
}
In this case, A is a supertype of B.
I hope this has been helpful.
A SortedSet needs to have some rules that it uses to determine the sorting. The Comparator is the implementation of these rules. The interface provides a method to get a reference to it so that you can use it for other purposes, such as creating another set that uses the same sorting rules.
From the javadoc:
"Returns the comparator used to order the elements in this set, or null if this set uses the natural ordering of its elements."
:)
"Super" here means that the method is not required to return a Comparator for E. It might instead return a Comparator for any superclass of E. So, to make that concrete, if E were String, this method could give you a more general Comparator for Object.
A generic method would declare a new generic parameter of its own. This method merely references the generic parameter E which was declared by the class declaration SortedSet<E>. Generic methods are less common. They are usually static, like the Arrays method
public static <T> List<T> asList(T...)
Here, T is declared and used only in this method. It shows that the type of the objects in the returned list is the same as the type of the objects in the vararg parameter.
I'm not sure the exact definition of wild card arguments. ? Is the wild card character. The general pattern when you get a wild card parameter like List<?> is that you can take objects out of it and cast them to Object but you can't put anything in.
The answer to this is in the interface declaration: public interface SortedSet<E> extends Set<E> { ...
This means that any class that implements SortedSet should specify which Type they will be working with. For example
class MyClass implements SortedSet<AnotherClass>
and this will produce (using eclipse), a bunch of methods such as
public Comparator<? super AnotherClass> comparator()
{
return null;
}
public boolean add( AnotherClass ac)
{
return false;
}
Of cause this will work with all sub-classes of AnotherClass as Paul Vargas pointed out.
The other aspect you might be missing is that Comparator is also an interface: public interface Comparator<T>. So what you are returning is an implementation of this.
Just for interest another useful way to use the Comparator interface is to specify it anonymously as part of the Arrays.sort(Object[] a, Comparator c) method:
If we had an Person class we could use this method to sort on age and name like this:
Person[] people = ....;
// Sort by Age
Arrays.sort(people, new Comparator<Person>()
{
public int compare( Person p1, Person p2 )
{
return p1.getAge().compareTo(p2.getAge());
}
});
// Sort by Name
Arrays.sort(people, new Comparator<Person>()
{
public int compare( Person p1, Person p2 )
{
return p1.getName().compareTo(p2.getName());
}
});

Java interface extends Comparable

I want to have an interface A parameterised by T A<T>, and also want every class that implements it to also implement Comparable (with T and its subtypes). It would seem natural to write interface A<T> extends Comparable<? extends T>, but that doesn't work. How should I do it then?
When Comparable<? extends T> appears it means you have an instance of Comparable that can be compared to one (unknown) subtype of T, not that it can be compared to any subtype of T.
But you don't need that, because a Comparable<T> can compare itself to any subtype of T anyway, e.g. a Comparable<Number> can compare itself to a Comparable<Double>.
So try:
interface A<T> extends Comparable<T> {
// ...
}
or
interface A<T extends Comparable<T>> extends Comparable<A<T>> {
// ...
}
depending on whether you need to be able to compare instances of T in order to implement your compareTo method.
If you use comparable you do not need to specify the possibility for subtypes in the compare function, it is by nature possible to pass in any subtype of an object X into a method that declared a parameter of class X. See the code below for more information.
public interface Test<T> extends Comparable<T> {
}
class TestImpl implements Test<Number> {
#Override
public int compareTo(final Number other) {
return other.intValue() - 128;
}
}
class TestMain {
public static void main(final String[] args) {
TestImpl testImpl = new TestImpl();
testImpl.compareTo(Integer.MIN_VALUE);
}
}

Categories