ConcurrentSkipListMap add Comparator defined in generic class - java

I have this class:
public abstract class Orderable<ID, T extends Comparable, V extends Orderable> implements Comparator<V>{
public abstract ID getId();
public abstract T getOrderParam();
public int compare(V o1, V o2) {
int compared = o1.getRankParam().compareTo(o2.getRankParam());
if (compared == 0) return o2.getId().toString().compareTo(o1.getId().toString());
return compared;
}
Now I'd like to create a ConcurrentSkipListMap passing as Comparator what I defined in Orderable Class. The goal is to keep ConcurrentSkipListMap ordered with comparator of V, where V is a generic class that extend Orderable.
private volatile ConcurrentSkipListMap<ID, V> concurrentSkipListMap;
private volatile AtomicInteger size;
public LeaderBoardImpl() {
concurrentSkipListMap = new ConcurrentSkipListMap<ID, V>(**** HERE I NEED TO PASS COMPARATOR****);
size = new AtomicInteger(0);
}
I'm not sure how to pass a Comparator of a generic Class.
Thanks
Albert

Related

How to sort a List of generic objects

I'm struggling with sorting an ArrayList of a generic objects.
I've tried to do it with Comparable interface, but it doesn't work, I've also tried with sort method of collections, but I'm still at the same point.
public class League<T extends Player> implements LeagueComparator<T> {
private String name;
private ArrayList<Team<T>> teams = new ArrayList<>();
public void ranking(){
for (Team<T> team : teams){
System.out.println(team.getName() + team.ranking());
int ranking = team.ranking();
Collections.sort(teams, new Comparator<Team<T>>() {
#Override
public int compare(Team<T> o1, Team<T> o2) {
return
In this method, I want to take a ranking integer from Team class and sort it, and then return the sorted values
public class Team<T extends Player> {
private int size = 0;
private String name;
private int games;
private int win;
private int lose;
private int draw;
private ArrayList<T> members = new ArrayList<>();
public int ranking(){
return (win * 2) + draw;
}
This is Team class
EDIT
System.out.println(team.ranking() + " " + team.getName());
Collections.sort(teams, Comparator.comparingInt(team::rankings));
System.out.println(team.ranking() + " " + team.getName());
Now it throws
Exception in thread "main"
java.util.ConcurrentModificationException
Comparable
I tried with Comparable interface but it doesn't work
If there's only one way to compare teams that make sense from the perspective of your application - by their ranking, then Team objects have a natural ordering and hence class Team should implement Comparable.
A quote from the documentation:
This interface imposes a total ordering on the objects of each class that implements it. This ordering is referred to as the class's natural ordering, and the class's compareTo method is referred to as its natural comparison method.
That's how it might be done:
public static class Team<T extends Player> implements Comparable<Team<T>> {
public static final Comparator<Team<? extends Player>> BY_TEAM_RANKING =
Comparator.comparingInt(Team::ranking);
// fields, getters, etc.
public int ranking() {
return (win * 2) + draw;
}
#Override
public int compareTo(Team<T> other) {
return BY_TEAM_RANKING.compare(this, other);
}
}
For the sake of conciseness, method compareTo in the code shown above internally uses Comparator defined as a static field (similar approach you can find in the book "Effective Java" by Joshua Bloch, have a look at it for more information on implementing Comparable interface).
To sort the list of teams, use method sort() directly on the list (which is a more fluent alternative of Collection.sort() introduced with Java 8).
public class League<T extends Player> {
private String name;
private List<Team<T>> teams = new ArrayList<>();
public void ranking() {
teams.sort(null); // teams are comparable, hence no need to provide a comparator and null is passed as an argument
}
}
Comparators
In case if there are multiple ways how teams need to be sorted in different scenarios, then Team class should not implement Comparable, don't go with way.
You can define comparators for different use-cases as public static fields in the Team class, like below:
public static class Team<T extends Player> {
public static final Comparator<Team<? extends Player>> BY_TEAM_RANKING =
Comparator.comparingInt(Team::ranking);
public static final Comparator<Team<? extends Player>> BY_TEAM_NAME =
Comparator.comparing(Team::getName);
// the rest code
}
And then apply them depending on a particular case:
public void ranking() {
teams.sort(Team.BY_TEAM_RANKING);
}
Sidenote: write your code against interfaces, not implementations like ArrayList. See What does it mean to "program to an interface"?
Simply returns the difference in ranking of o1 and o2.
Collections.sort(teams, new Comparator<Team<T>>() {
#Override
public int compare(Team<T> o1, Team<T> o2) {
return o1.ranking() - o2.randking();
}
});

Need to add Comparable without modifying the class that is comparing

Code:
LinkedBinarySearchTree <Pair<String, Integer>> at = new LinkedBinarySearchTree<>();
Pair<String, Integer> p = new Pair<>(str, dni);
at.insert(p);
Pair is a class that has been given to me, it isn't the java class Pair (idk if java has a default pair class but just in case it has one, this one isn't that).
The class pair doesn't have a compareTo defined in it and the method insert uses the compareTo at some point and when it does it crashes.
I need to implement the abstract class Comparable and override the method compareTo in the class from the outside, without modifying the code of the class Pair, which means I have to do it from the "outside".
Is there a way to do this?
This is what I did previously:
public class MyComparator implements Comparator <Pair<String, Integer>> {
#Override
public int compare(Pair<String, Integer> o1, Pair<String, Integer> o2) {
final Collator instance = Collator.getInstance();
instance.setStrength(Collator.NO_DECOMPOSITION);
if (!o1.getFirst().equals(o2.getFirst())){
return o1.getFirst().compareTo(o2.getFirst());
} else {
return o1.getSecond().compareTo(o2.getSecond());
}
}
}
But it doesn't work with Comparator, it has to be Comparable for some reason and I don't know how to do it because I can't refer (this):
public class MyComparable implements Comparable <Pair<String, Integer>> {
#Override
public int compareTo(Pair<String, Integer> o) {
final Collator instance = Collator.getInstance();
instance.setStrength(Collator.NO_DECOMPOSITION);
//I can't use "this" here because ovbiously I'm not inside the class Pair so I don't know how to do it
if (!this.getFirst().equals(o.getFirst())){ //I can't use "this"
return this.getFirst().compareTo(o.getFirst());
} else {
return this.getSecond().compareTo(o.getSecond());
}
}
}
I need help please I've been trying to find an answer by myself and I'm out of ideas... I'm sorry if this question is too easy or unhelpful but I'm kinda struggling here :/.
EDIT:
I debugged the program and this is where it crashes, that's why I
think I need the Comparable:
public class DefaultComparator<E> implements Comparator<E> {
#Override
public int compare(E a, E b) throws ClassCastException {
return ((Comparable<E>) a).compareTo(b); //here
}
}
Could you possibly extend Pair with you own class that also implements Comparable and use that?
public class MyPair<T, O> extends Pair<T, O> implements Comparable<MyPair<T, O>> {
#Override
public int compareTo(MyPair<T, O> other) {
//logic to compare
}
}
and then use that
LinkedBinarySearchTree <MyPair<String, Integer>> at = new LinkedBinarySearchTree<>();
Edit based on comments:
If you know the types of objects used in the Pair are themselves Comparable then you can use bounded generic parameters. So the example above becomes:
public class MyPair<T extends Comparable<T>, O extends Comparable<O>> extends Pair<T, O> implements Comparable<MyPair<T, O>> {
#Override
public int compareTo(MyPair<T, O> other) {
//Now the compiler knows that T and O types are Comparable (that
//is they implement the Comparable interface) and
//this means their compareTo() can be used
return this.getFirst().compareTo(other.getFirst());
}
}
You can create a wrapper class to pair without changing pair but adding comparable to wrapper and after that you need to change your linkedlist's generic to ComparablePair
class ComparablePair implements Comparable < ComparablePair > {
private Pair < String,Integer > pair;
#Override
public int compareTo(ComparablePair o) {
Pair otherPair = o.pair;
//compare this.pair and otherpair here.
return 0;
}
}
LinkedBinarySearchTree <ComparablePair> at = new LinkedBinarySearchTree<>();

how does this statement works: "static final Comparator<Employee> SENIORITY_ORDER = new Comparator<Employee>() {};"

I'm learning Java and I saw the code below on Youtube. I was just wondering how this part of the code works.
static final Comparator<Employee> SENIORITY_ORDER =
new Comparator<Employee>() {
public int compare(Employee e1, Employee e2) {
return e2.hireDate().compareTo(e1.hireDate());
}
};
Could someoen please explain it to me? Thanks in advance for any help!
import java.util.*;
public class EmpSort {
static final Comparator<Employee> SENIORITY_ORDER =
new Comparator<Employee>() {
public int compare(Employee e1, Employee e2) {
return e2.hireDate().compareTo(e1.hireDate());
}
};
// Employee database
static final Collection<Employee> employees = ... ;
public static void main(String[] args) {
List<Employee> e = new ArrayList<Employee>(employees);
Collections.sort(e, SENIORITY_ORDER);
System.out.println(e);
}
}
The SENIORITY_ORDER Comparator (used for comparing Employees in the sort) is an Anonymous Class. The linked Java Tutorial reads (in part)
Anonymous classes enable you to make your code more concise. They enable you to declare and instantiate a class at the same time. They are like local classes except that they do not have a name. Use them if you need to use a local class only once.
Well as we all konw . the Comparator is the rule that how to compare tow Object.
you can come into this Method : Collections.sort(e, SENIORITY_ORDER);
and you will see the answer you want
public static <T> void sort(List<T> list, Comparator<? super T> c) {
Object[] a = list.toArray();
Arrays.sort(a, (Comparator)c); //this is your rule to compare
ListIterator i = list.listIterator();
for (int j=0; j<a.length; j++) {
i.next();
i.set(a[j]);
}
}
if your Object not implements comparable so you must have a comparetor
or it's will be a wrong. The Collections.sort will to call the compare() Method.
static final Comparator<Employee> SENIORITY_ORDER =
new Comparator<Employee>() {
public int compare(Employee e1, Employee e2) {
return e2.hireDate().compareTo(e1.hireDate());
}
};
The statement static final Comparator<Employee> SENIORITY_ORDER = new Comparator<Employee>(){}
is creating a reference of the Comparator<Employee> interface that points to an instance of an Anonymous Inner Class which implements the Comparator<Employee> interface. Hence, you are overrding the compare() method of Comparator Interface inside your anonymous class.
Inside the compare() method you are comparing the hireDate attribute of two Employee objects using the compareTo() method of the Comparable interface in java. This method, compareTo(), compares the two attributes i.e, e1.hireDate and e2.hireDate, lexicographically and returns either a positive integer, a negative integer or zero, depending on whether e2.hireDate is greater than, less than or equal to e1.hireDate.
(HOPE YOU ARE ALREADY AWARE WITH THE CONCEPTS OF COMPARATOR INTERFACE AND NESTED CLASSES IN JAVA)

Declaring generics

I have a problem with defining generics in static methods and fields.
Suppose I have a simple interface, used by all classes that contains a field of type T called value:
public interface HasValue<T> {
// Getter:
public T value();
// Setter:
public void setValue(T value);
}
If I have an array of object of a type N that implements HasValue<T>, I may have necessity to order this array. One classical way is to compare those N objects using their value field: if T implements the Comparable<T> interface and both arg0 and arg1 are of type N, then arg0.compareTo(arg1) will be equal to arg0.value().compareTo(arg1.value()).
The goal is to create a usable, not time-consuming, possible simple way to obtain the aforementioned situation.
A possibility would be to create a custom Comparator<N> every time I need something similar. That would force me to write code each time: definitly time consuming.
I could create that Comparator<N> directly in the interface. The first try is to create a method:
It needs to be a default method. Part of the code will test if the class T implements the Comparable interface or not, and for that I need an example of the T class: using this.value().getClass() is the fastest way. With a static method I could not use this.
I need to explicitate that the N class implements the interface HasValue<T>, otherwise the computer will not know.
public default <N extends HasValue<T>> Comparator<N> COMPARE_BY_VALUE() throws Exception{
if(Comparable.class.isAssignableFrom(this.value().getClass()))
return new Comparator<N>() {
public int compare(N arg0, N arg1) {
Comparable value0 = (Comparable) arg0.value(),
value1 = (Comparable) arg1.value();
return value0.compareTo(value1);
}
};
else throw new Exception("The class of the value does not implement the interface Comparable.\n");
}
This strategy works... barely. It's clumsy, involves rawtypes, creates the Comparator<N> every time.
Second try: creating a static field.
The strategy is to separate the testing problem from the rest. A default method will do the test: in case of success the method will return a static Comparator, otherwise an exception.
public default <N extends HasValue<T>> Comparator<?> COMPARE_BY_VALUE() throws Exception{
if(Comparable.class.isAssignableFrom(this.value().getClass()))
return COMPARE_BY_VALUE;
else throw new Exception("The class of the value does not implement the interface Comparable.\n");
}
public static Comparator<HasValue> COMPARE_BY_VALUE = new Comparator() {
public int compare(Object arg0, Object arg1) {
Comparable value0 = (Comparable) ((HasValue)arg0).value(),
value1 = (Comparable) ((HasValue)arg1).value();
return value0.compareTo(value1);
}
};
While declaring the static field I (unfortunately) cannot state something like public static <T, N extends HasValue<T>> Comparator<N> COMPARE_BY_VALUE. That forces me to return a Comparator<HasValue>: not what I wanted.
Using wildcards I can obtain something close:
public default <N extends HasValue<T>> Comparator<?> COMPARE_BY_VALUE() throws Exception{
if(Confrontable.class.isAssignableFrom(this.value().getClass()))
return COMPARE_BY_VALUE;
else throw new Exception("The class of the value does not implement the interface Comparable.\n");
}
public static Comparator<? extends HasValue<? extends Comparable<?>>> COMPARE_BY_VALUE
= new Comparator() {
public int compare(Object arg0, Object arg1) {
Comparable value0 = (Confrontable) ((HasValue<?>)arg0).value(), value1 = (Confrontable) ((HasValue<?>)arg1).value();
return value0.compareTo(value1);
}
};
This modification will return (in theory) a Comparator<N> where N extends HasValue<T>, T extends Comparable<U> and U is actually T.
That because every ? in Comparator<? extends HasValue<? extends Comparable<?>>> is interpreted by the JVM as a potential new class: three ? means three new class (N, T and U), and it happens that T implements Comparable<T> - thus U and T are one and the same.
I still have a great amount of rawtypes...
...but at least I have only one Comparator for each N and T.
Now, while the last strategy seems to works, I would like to know if there is a better way to obtain my goal.
My initial idea was to state something like
public static <T extends Comparable<T>, N extends HasValue<T>> Comparator<N> COMPARE_BY_VALUE = new Comparator() {
public int compare(N arg0, N arg1) {
return arg0.value().compareTo(arg1.value());
}
};
and obtain a Comparator<N> without wildcars. This however sends all types of errors. Someone has an idea?
Just do:
static <T extends Comparable<T>> Comparator<HasValue<T>> createValueComparator() {
return new Comparator<HasValue<T>>() {
#Override
public int compare(HasValue<T> o1, HasValue<T> o2) {
return o1.value().compareTo(o2.value());
}
};
}
This reads: for every type T which implements Comparable this method returns comparator which can compare HasValue<T>.
Java might not be able to properly infer types in such convoluted constructs. You might have to add the types explicitly:
Collections.sort(list, Main.<Integer> createValueComparator());
or:
Comparator<HasValue<Integer>> comparator = createValueComparator();
Collections.sort(list, comparator);
Keep in mind that a lot of programmers overuse generics. Usually there is a simpler way to achieve the same - while still maintaining type safety.

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.

Categories