Java using Comparator - java

I am implementing Comparator and Comparable in my class Employee to sort an arraylist. I am sorting on 2 parameters name and ID. While sorting with ID using Collections.sort(Employee ob1, Employee ob2) it doesn't work. I get the compilation error that the class is not declared abstact and i am not overriding compare(), although i am doing it as:
public int compare(Employee ob1, Employee ob2)
{
return ob1.id-ob2.id;
}
it works fine if i use
public int compare(Object ob1, Object ob2)
{
return ((Employee)ob1).id-((Employee)ob2).id;
}
My doubt is why does't the earlier one work since Employee is also an Object.
The same issue is with compareTo(Object ob) as well, While overriding why can't i use Employee directly and why do i need to use Object there and later need to cast it to Employee class.

Polymorphism, using Object, Object overrides a raw-type in Comparator. Using your class names doesn't match that signature. For a compile error when you mix up the signature use the template type.
public class Employee implements Comparator<Employee> {
// ....
#Override
public int compare(Employee ob1, Employee ob2) {
return ob1.id-ob2.id;
}
}

You need to implement the exact methode the interface defines.
If you want to work directly with your Object use the <> generic syntax:
public class Employee implements Comparator<Employee>
{
#Override
public int compare(Employee ob1, Employee ob2)
{
return ob1.id - ob2.id;
}
}
Make sure to use the #Override Annotation. This will give you a compiler warning if you get the methode wrong (parameter, return values etc.)
When using Comparable you can use it like this:
public class Employee implements Comparable<Employee>
{
#Override
public int compareTo(Employee e)
{
//your compare code
}
}
See also: Comparable vs Comparator

Related

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)

What's alternative NSSortDescriptor in Java?

I hava ArrayList which is include Custom Data Class.
ArrayList<MyData> list
Custom Data class has several field
class MyData {
private int num;
private String name;
etc....
getter/setter...
}
I want to sort List by field (ex:num)
Objecitive-C has NSSortDescriptor which can sort objects.
NSSortDescriptor Class Reference
is There alternative this? or other solution?
You can use Comparable and Comparator interface.. and the use Collection.sort().
You need to implement Comparable and Comparator interface, if you are using Collection of Custom Type(i.e not primitive types).
For detailed examples check http://www.mkyong.com/java/java-object-sorting-example-comparable-and-comparator/
Hope this post will be helpful to u.
Implement Comparable or Comparator and use Collections.sort().
Comparable
public class MyClass implements Comparable<MyClass>{
public int x;
public int compareTo(MyClass mc){
return x - mc.x;
}
}
Comparator
public class MyClass{
public int x;
}
public class MyClassComparator implements Comparator<MyClass>{
public int compare(MyClass mc1, MyClass mc2){
return mc1.x - mc2.x;
}
}
java.util.Comparator coupled with java.util.Collection.sort should do the trick.
You could also have MyData implement java.util.Comparable and use the other sort method, but that isn't quite as flexible.
There is nothing similar to NSSortDescriptor in Java: Java sorting uses the style that is more similar to the sortUsingComparator: method of the NSMutableArray class:
Collections.sort(list, new Comparator<MyData>() {
// This is similar to the comparator block of Cocoa
public int compare(MyData o1, MyData o2) {
// Put the comparison code here
...
}
});

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.

Sorting problem cannot instantiate abstract object overriding compareTo() Method

I'm trying to establish a new sort criteria, in this case by name.
I'm facing an error when I call the sort method...
this is a separated class (SortByName) in package "package":
-----------------------CLASS SortByName---------------------------
package package;
import java.util.*;
public abstract class SortByName implements Comparator{
public int compareTo(Object o1, Object o2){
String n1 = ((Ficha)o1).getName();
String n2 = ((Ficha)o2).getName();
return n1.compareTo(n2);
}
and then inside an ActionPerformed event I have this:
----------------IN THE ACTION EVENT BUTTON----------------------------
Collections.sort( list , new SortByName() );
"package.SortByName is abstract,> cannot be instantiated"
I tried changing the "abstract" type in the class definition (SortByName) , but it complies about not overriding the compareTo() method.
thanks for reading.
The method you have to implement is called compare, not compareTo.
Abstract classes cannot be instantiated.
Also, Comparator is generic, so you'd better do the following:
public class SortByName implements Comparator<Ficha>{
public int compareTo(Ficha f1, Ficha f2){
String n1 = f1.getName();
String n2 = f2.getName();
return n1.compareTo(n2);
}
}
Comparator needs to implement compare(), not compareTo() method.
class SortByName implements Comparator<Ficha>{
#Override
public int compare(Ficha o1, Ficha o2) {
String n1 = o1.getName();
String n2 = o2.getName();
return n1.compareTo(n2);
}
}
You need to remove "abstract" and implement the equals method as well.
Code should look like:
package package;
import java.util.*;
public class SortByName implements Comparator{
public int compare(Object o1, Object o2){
String n1 = ((Ficha)o1).getName();
String n2 = ((Ficha)o2).getName();
return n1.compareTo(n2);
}
public boolean equals(Object o1) {
// code which compares the current comparator (!) with the object given
}
Note that you might need to use specialized comparators if compiling against a version of java which supports generics. Not sure if this is correct but I think you can do something like:
public class SortByName implements Comparator <Ficha> {
public int compare(Ficha o1, Ficha o2){
// comparing code here
}
}
But again, not entirely sure on that part, you need to test it a bit.
If you check out the Comparator API that will explain how you must implement equals.
Also note that the Comparator interface defines compare, not compareTo.
Laura you were right I had to add the equals method.( u missed the return value)
also remove "abstract" at class definition.
and change compareTo() with compare().
thanks a lot Laura, PROBLEM SOLVED !!!!

How do I implement a Comparator using Generics?

Just a minor problem with Arraylist. I want to sort a ArrayList<Client> by name.
Class Client{ String name; int phonenumber ..}
This code does the work, but i'm having a compiler warning: "uses unchecked or unsafe operations". Whats the problem?
public void sortByName(){
Collections.sort(ListofClients, new NameComparator());
}
My comparator looks like this:
public class NameComparator implements Comparator{
public int compare(Object client1, Object client) {
String name1 = ((Client) client1).getName();
String name2 = ((Client) client2).getName();
return name1.toUpperCase()).compareTo(name2.toUpperCase();
}
}
If i use "implements Comparator<Client> " i get a error: "NameComparator is not a abstract and does not override abstract method compare(Client, Client) in java.util.Comparator. Is my comparator wrong? sorry for this noob question, new to java
After you implement Comparator<Client> you need to change:
public int compare(Object client1, Object client)
{
...
}
to this
public int compare(Client client1, Client client)
{
// Now you don't have to cast your objects!
}
this is all because the definition of comparator
public interface Comparator<T>
{
public compare(T o1, T o2);
}
Notice how the generic parameter T shows up in the method name.
An IDE like Eclipse / Netbeans / IntelliJ will help out in this situation.
I presume your list of clients is of the type
List<Client>
in which case your comparator should be of type Comparator<Client>, and perform the appropriate comparison (by name, in this case)

Categories