I have an object of a custom type called Suffix which is defined as
class Suffix
{
int index;
String suff;
}
I create an Array of objects of type suffix
Suffix s[] = new Suffix[10];
I need to sort it according to the string suff data member. How can I do that? I am unable to understand most of the custom implementations available online.
eg :
If I have s[0].suff = "hats",s[1].suff = "ats", s[2].suff ="ts". Now I need to sort this array based on the suffix. ("ats",1) , ("hats",0) and ("ts",2) should be sorted order.
You can use Arrays.sort(..) if your object extends Comparable interface.
class Suffix implements Comparable<Suffix>
{
int index;
String suff;
#Override
public int compareTo(Suffix o) {
return this.suff.compareTo(o.suff);
}
}
You can use as below now
Suffix s[] = new Suffix[10];
Arrays.sort(s);
You got three possibilities:
Write your own sorting algorithm and compare the suff String there.
Implements the Comparable<> interface in your Suffix class, Override the comparteTo() method and use Arrays.sort(); which takes the array of Compareable objects as parameter.
Wirte a Comparator<> and use the Arrays.sort() method which takes the array and the Comparator.
The third way have one advantage. If you want to sort by index instead of suff param, you can pass another Comparator to the sort() method.
Suffix s[] = new Suffix[10];
Comparator comp = new Comparator<Suffix>(){
#Override
public int compare(Suffix arg0, Suffix arg1)
{
return arg0.suff.compareTo(arg1.suff);
}
};
Arrays.sort(s,comp);
You have nothing to change in your Suffix class. Hint: You can make an extra class with your Comparators as static fields.
Apart from using Comparable as #insert-username-here and #vinayknl said, The other one is using Comparator. Inside the method you want to sort add the following:
Comparator comparator = new Comparator<Suffix>() {
public int compare(Object o1, Object o2) {
Suffix s1 = (Suffix) o1;
Suffix s2 = (Suffix) o2;
return s1.getSuff().compareTo(s2.getSuff());
}
}
Array.sort(s, comparator);
Note: don't forget to add getter.
Check out the Comparable interface. This interface will allow your classes to be compared according to your own criteria.
Quick google search came up with this helpful page.
Related
Is there is a built-in method in Java to sort a 2D array directly
For example: if I have an array of first name & phone number, can I sort it according to the first name while each name will keep it's phone number using built-in function?
Is your data structure [[name1, name2, ...], [phone1, phone2,...]] or [[name1, phone1], ...]? If it's the latter, you can use a comparator.
class NameAndPhoneComparator implements Comparator<String[]> {
public int compare(String[] o1, String[] o2) {
int c = o1[0].compareTo(o2[0]);
if (c != 0) return c;
return o1[1].compareTo(o2[1]);
}
}
Then use Arrays.sort
Make your 2d Array into a 1D array of the below class, then use built in methods with a custom Comparator to do the sorting. You could also make this class Comparable to itself.
class Person{
public String name;
public String phNumber;
}
Alternatively use a TreeMap,as sansix suggests, with the key as the name and value as phNumber. There would be no need for a comparator any more, and the Data will always be sorted.
I have a list of objects:
List<WorkflowError> workflowErrors = new List<WorkflowError>();
Of which I am wanting to sort alphabetically on the string field errorCode.
I know I have to use
Collections.sort(list,comparator)
and write a custom Comparator:
public class SortByErrorComparator implements Comparator<WorkflowError>
{
// Comparator logic
return 0;
}
I have seen examples of how to do this for a one dimensional list but I can't work out how to begin for a list of objects.
Any help would be appreciated.
You need to implement the compare method.
public class SortByErrorComparator implements Comparator<WorkflowError> {
public int compare(WorkflowError obj1, WorkflowError obj2) {
return obj1.getErrorCode().compareTo(obj2.getErrorCode());
}
}
And then, you can simply do:
Collections.sort(list, new SortByErrorComparator()) ;
In the Java world, generally we do it inline using anonymous inner classes as so:
Collections.sort(list, new Comparator<WorkflowError>() {
public int compare(WorkflowError obj1, WorkflowError obj2) {
return obj1.getErrorCode().compareTo(obj2.getErrorCode());
}
});
In your comparator, you have to explain how the specific object should be sorted.
if (obj.att1 < obj2.att2)
...
do you get it?
When sorting the list the sort implementation will use your comparator to compare individual paisr of objects. So what your comparator needs to do is decide, for a given pair of WorkFlowErrors, which comes 'first'.
from what you've said this sounds like just getting the error code from each one and doing a string compairson.
If you will always want to compare WorkflowError objects in this manner, the easiest way is to implement Comparable<WorkflowError> on WorkflowError itself.
public int compareTo(WorkflowError that) {
return this.getErrorCode().compareTo(that.getErrorCode());
}
That's assuming errorCode implements Comparable.
I have a class which has a String field called name. I have an array of type SomeClass[] and I want to iterate through these SomeClass objects in String order on their names.
I'm curious as to what the most efficient way to do this would be. Should I use a comparator of some sort? Would it be a good idea to put them all into a TreeMap and then iterate through that or something similar? I'm sure I could come up with a solution, but I'm also sure that it would be less than efficient.
Any help is appreciated.
You can just Arrays.sort your Comparable class, like Arrays.sort(a) (see the code)
Or, if you wanted to use Collections framework
Arrays.asList(...) and Collections.sort(..) is the key.
IF SomeClass is like this
public class SomeClass implements Comparable<SomeClass>{
public String val;
#Override
public int compareTo(SomeClass that) {
return this.val.compareTo(that.val);
}
#Override
public String toString() {
return this.val;
}
}
yo can sort like this
SomeClass o = new SomeClass();
o.val = "z";
SomeClass t = new SomeClass();
t.val = "a";
SomeClass th = new SomeClass();
th.val = "m";
SomeClass[] a = new SomeClass[]{o, t, th};
//this
Arrays.sort(a);
//or this
List<SomeClass> l = Arrays.asList(a);
System.out.println(l);
Collections.sort(l);
System.out.println(l);
Put your Classes in an Arraylist and use its sort method.
Unverified code:
yourArray.sort(new YourNameComparator());
class YourNameComparator implements Comparator<YourNameClass> {
int compare(YourNameClass y1, YourNameClass y2) {
return y1.getName().compareTo(y2.getName());
}
}
In my opinion, your best bet would be to, as you say, put it in a TreeMap (or some data structure that sorts it for you) and then read it out already sorted. There's hardly a way to get faster, and this way would produce the cleanest and most readable code.
Your two options: have your class implement comparable and write a compareTo method or create a comparator and feed that into Collections.sort(List list, Comparator c)
Since you want to compare strings, you probably want to use comparable since StringY.compareTo(String x) already exists.
http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Comparable.html
http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Collections.html
Here is my Code
class ComparableTest
{
public static void main(String[] args)
{
BOX[] box = new BOX[5];
box[0] = new BOX(10,8,6);
box[1] = new BOX(5,10,5);
box[2] = new BOX(8,8,8);
box[3] = new BOX(10,20,30);
box[4] = new BOX(1,2,3);
Arrays.sort(box);
for(int i=0;i<box.length;i++)
System.out.println(box[i]);
}
}
Also i have a class BOX that implements Comparable.
Now i have a few question that i would like you all to help me out with.
1.Are the methods declared in comparable interface,system defined, as in can i have any method in the comparable, or it has to be compareTo only?
2.I did not provide the implementation of Arrays.sort method, how does it sort my elements then?
3.When i use Comparator instead of comparable, then I use:
class comparatorTest
{
public static void main(String args[])
{
Student[] students = new Student[5];
Student[0] = new Student(“John”,”2000A1Ps234”,23,”Pilani”);
Student[1] = new Student(“Meera”,”2001A1Ps234”,23,”Pilani”);
Student[2] = new Student(“Kamal”,”2001A1Ps344”,23,”Pilani”);
Student[3] = new Student(“Ram”,”2000A2Ps644”,23,”Pilani”);
Student[4] = new Student(“Sham”,”2000A7Ps543”,23,”Pilani”);
// Sort By Name
Comparator c1 = new studentbyname();
Arrays.sort(students,c1);
for(int i=0;i<students.length;i++)
System.out.println(students[i]);
}
}
//In the above code, studentbyname implements comparator, but box stil implements comparable .i.e
class studentbyname implements comparator
{
public int compare(Object o1,Object o2)
{
Student s1 = (Student) o1;
Student s2 = (Student) o2;
return s1.getName().compareTo(s2.getName());
}
}
Now i am doing Arrays.sort(students,c1), why am i passing c1 now?
In order to meet the Comparable contract, you must have at least the compareTo method. You may have as many addition methods in your class as you would like.
It sorts the elements in the natural order based on the Comparable interface. So sort is calling compareTo between the elements to see in which order to place them.
Providing a Comparator to the sort method allows sort to order elements that either (a) don't implement Comparable or (b) where you want to order them in some other order than the "natural order" as defined by the class's Comparable implementation.
When you pass a Comparator to sort, it calls the Comparator's compare method rather than the elements' compareTo method (if implemented).
see What is an interface
see Comparator
see Comparable
You can define as many methods as you want in a Comparable, as long as you implement compareTo. This method can be used in many situations where the class is checked for comparation. For example, when inserting instances into an ordered TreeSet. compareTo provides a general ordering rule for all instances of the class.
Arrays.sort orders the array in the natural order of its elements. That is, using compareTo.
You can use Comparator to define a custom ordering rule. Like when you have a table you can sort by any of its columns. You could define a Comparator for each of its columns, and you could still have a class-inherent ordering rule (as in related to the reality the Class represents) defined in the class' compareTo.
Implementing Comparable obligates you to provide an implementation for compareTo().
All elements in the Object array passed to the Arrays.sort(Object[]) method must implement Comparable. If you want to use a Comparator instead, you have to use an Arrays.sort() method that takes a Comparator as a parameter. The method you use in your example above takes a Comparator as the second parameter - hence the need to provide c1 in the method call.
Basically, I have a Container class called "Employees" which has in it an ArrayList. This ArrayList contains "Employee" objects, which in turn contain "EmployeeData" objects which in turn contain String objects such as "first" or "last" (which are employee names).
Here's a diagram of the ArrayList structure:
ArrayList[Employee] emps ==> 1:Many ==> Employee emp
Employee emp ==> 1:1 ==> EmployeeData data
EmployeeData data ==> 1:2 ==> String last // A string that contains employee's last name.
How in the world would I perform a quicksort on the ArrayList so that the "Employee" objects in it are in alphabetical order based on the String object "last"? It seems kinda complicated!
Here's a basic design of my classes:
class Employees{
//data:
private ArrayList<Employee> emps = new ArrayList<Employee>();
//Some constructors go here
//Methods to add, remove, toString, etc, go here
public /*output a sorted ArrayList?*/ sort(){
// Some kind of "quicksort" in here to modify or create a new ArrayList sorted by employee's las name...
}
}
class Employee{
//data:
EmployeeData data;
// Some methods to construct and modify EmployeeData data.
}
class EmployeeData{
//data:
String first, last; // I wish to sort with "last". How do you do it?
double payrate, hours;
//...methods...
}
As you can see, those are the classes. I have no idea how to implement "sort" in the "Employees" class so that it sorts the ArrayList by the "last" variable of the "EmployeeData" class.
You can make a comparator, something like:
public class MyComparator implements Comparator<Employee>
{
public int compare(Employee e1, Employee e2)
{
return e1.getData().getLast().compareTo(e2.getData().getLast());
}
}
Then use it to sort the list.
Collections.sort(myList, new MyComparator());
Alternatively, you can use a TreeSet to sort on insertion using this comparator or make the Employee a comparable object to sort using Collections or a SortedSet.
public class Employee implements Comperable<Employee>
{
...
public int compareTo(Employee e)
{
return this.getData().getLast().compareTo(e.getData().getLast());
}
...
}
Define Employee implements Comparable<Employee>.
In the compareTo method, dig into the layers and compare the strings you need. Then you can use Collections.sort(), or you can store the data in a SortedSet, which is naturally ordered.
The best practice is to encapsulate the sorting logic in the class stored in the ArrayList, Employee in this case. Implement Comparable by creating a compareTo(Employee) method.
import java.util.*;
public class Employee implements Comparable<Employee> {
public EmployeeData Data;
public Employee(String first, String last)
{
Data = new EmployeeData(first, last);
}
public int compareTo(Employee other)
{
return Data.Last.compareTo(other.Data.Last);
}
public String toString() {
return Data.First + " " + Data.Last;
}
public static void main(String[] args) throws java.io.IOException {
ArrayList list = new ArrayList();
list.add(new Employee("Andy", "Smith"));
list.add(new Employee("John", "Williams"));
list.add(new Employee("Bob", "Jones"));
list.add(new Employee("Abraham", "Abrams"));
Collections.sort(list);
for (int i = 0; i < list.size(); i++)
{
System.out.println(list.get(i));
}
System.in.read();
}
}
public class EmployeeData {
public String First;
public String Last;
public EmployeeData(String first, String last)
{
First = first;
Last = last;
}
}
Output:
Abraham Abrams
Bob Jones
Andy Smith
John Williams
Peter DeWeese and others have given you very good answers. You can use
Collections.sort(myList, new MyComparator());
to sort myList using a Comparator you have defined. <=== What the heck does that mean?
In Java, if something implements Comparable (java.lang.comparable) then you can define an order for your elements. It seems like you know what Java Generics are, as you used them to declare your ArrayList as being of type < Employee >. This is awesome, because you can store an Employee object into each entry in the ArrayList. So far so good?
However, if you want to sort objects, first you have to define an order. Since objects can have various properties, maybe I want to sort my employees by ear-size. In this case, I simply tell Java that my class implements Comparable. With generics, I have to specify that it implements Comparable< Employee > because I am defining an order for my Employee objects (peons, minions, whatever).
Peter DeWeese mentioned:
public int compareTo(Employee e)
{
return this.getData().getLast().compareTo(e.getData().getLast());
}
and Jason Goemaat mentioned:
public int compareTo(Employee other)
{
return Data.Last.compareTo(other.Data.Last);
}
What the heck does this mean? If I say that my class implements Comparable then I need to define a compareTo function. (An interface is a collection of methods that need to be implemented) The function compareTo defines the order of my elements.
From the Comparable< T> spec:
int compareTo(T o)
Compares this object with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
If I am comparing ear sizes, and let's say I want big ears to come first in my list, then I could (re)define compareTo as:
public int compareTo(Employee e)
{
if (this.earSize > e.earSize) //big ears come first
return -1;
if (this.earSize == e.earSize) //equality
return 0;
else
return 1; // if e.earSize > this.earSize then return 1
}
To answer Steve Kuo's question, we put the keyword this in our comparator because when we call the compareTo method
x.compareTo(y);
the keyword this will refer to x.
You can think of compareTo as being a method of the object x, so when you call x.compareTo(y) you are really saying this.compareTo(y) from within the scope of object x.
We can also look at a String example:
This means that if I want "Medvedev" to come before "Putin" (as 'M' comes before 'P' in the English alphabet) I would have to state that I want compareTo to return -1 when comparing Medvedev to Putin.
String TheMString = "Medvedev";
String ThePString = "Putin";
then the line
TheMString.compareTo(ThePString);
will evaluate to -1.
Now a standard routine such as Collections.sort(list, comparator) will be able to use these values that compareTo returns to figure out the [absolute] order of list. As you may know, sorting is a comparison based operation and we need to know what value is "less than" or "greater than" another value in order to have a meaningful sort.
One big caveat is that if you call compareTo on Strings, it defaults to alphabetical order, so you may simply tell compareTo to return A.compareto(B) and it will make sure the strings are in order.
Normally (well, I should say, in other cases) when redefining the compareTo method, you must explicitly state a neg/zero/pos return value.
I hope that helps.