133

Im trying to sort through an arraylist of objects by a particular value within the object. What would be the best approach to do such a thing. Should I use Collections.sort() with some kind of comparator?

Im trying to sort a list of objects by a float value they hold in one of the variables.

EDIT: This is what I have so far:

public class CustomComparator implements Comparator<Marker> {
 @Override
 public int compare(Mark o1, Mark o2) {
 return o1.getDistance().compareTo(o2.getDistance());
 }
}

the error states: Cannot invoke compareTo(double) on the primitive type double.

Is it because a comparator cant return anything other than a certain type?

asked Feb 2, 2012 at 9:29
3
  • 2
    "Should I use Collections.sort() with some kind of comparator? " Yes, sounds like a good idea Commented Feb 2, 2012 at 9:31
  • I dont know if it matters but the number of objects in the list will be as high as 80. Thats why Im kind of confused about using a comparator if that is the way to go because it only compares two values at once. Commented Feb 2, 2012 at 9:33
  • That's how the sorting works. First add one item to a list. When adding next; should this go before or after current in the list. When adding third item compare to first item in list, if after then compare to next item. And so on. Commented Feb 2, 2012 at 9:41

15 Answers 15

431

Follow this code to sort any ArrayList

Collections.sort(myList, new Comparator<EmployeeClass>(){
 public int compare(EmployeeClass obj1, EmployeeClass obj2) {
 // ## Ascending order
 return obj1.firstName.compareToIgnoreCase(obj2.firstName); // To compare string values
 // return Integer.valueOf(obj1.empId).compareTo(Integer.valueOf(obj2.empId)); // To compare integer values
 // ## Descending order
 // return obj2.firstName.compareToIgnoreCase(obj1.firstName); // To compare string values
 // return Integer.valueOf(obj2.empId).compareTo(Integer.valueOf(obj1.empId)); // To compare integer values
 }
 });
answered Dec 11, 2012 at 13:36
3
  • This example works for comparing strings. For sorting by comparing integers look at Pranav's answer below. Commented Aug 25, 2016 at 13:41
  • @Themelis it's java function Commented Jul 24, 2019 at 15:51
  • 4
    int compare can be replaced by: return Integer.compare(obj1.empId, obj2.empId); Commented Oct 13, 2019 at 17:40
104

You should use Comparable instead of a Comparator if a default sort is what your looking for.

See here, this may be of some help - When should a class be Comparable and/or Comparator?

Try this -

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class TestSort {
 public static void main(String args[]){
 ToSort toSort1 = new ToSort(new Float(3), "3");
 ToSort toSort2 = new ToSort(new Float(6), "6");
 ToSort toSort3 = new ToSort(new Float(9), "9");
 ToSort toSort4 = new ToSort(new Float(1), "1");
 ToSort toSort5 = new ToSort(new Float(5), "5");
 ToSort toSort6 = new ToSort(new Float(0), "0");
 ToSort toSort7 = new ToSort(new Float(3), "3");
 ToSort toSort8 = new ToSort(new Float(-3), "-3");
 List<ToSort> sortList = new ArrayList<ToSort>();
 sortList.add(toSort1);
 sortList.add(toSort2);
 sortList.add(toSort3);
 sortList.add(toSort4);
 sortList.add(toSort5);
 sortList.add(toSort6);
 sortList.add(toSort7);
 sortList.add(toSort8);
 Collections.sort(sortList);
 for(ToSort toSort : sortList){
 System.out.println(toSort.toString());
 }
 }
}
public class ToSort implements Comparable<ToSort> {
 private Float val;
 private String id;
 public ToSort(Float val, String id){
 this.val = val;
 this.id = id;
 }
 @Override
 public int compareTo(ToSort f) {
 if (val.floatValue() > f.val.floatValue()) {
 return 1;
 }
 else if (val.floatValue() < f.val.floatValue()) {
 return -1;
 }
 else {
 return 0;
 }
 }
 @Override
 public String toString(){
 return this.id;
 }
}
answered Feb 2, 2012 at 9:35
1
  • 1
    Hey thanks for the link :) I go back and forth from one language to the next so Im always missing something :p you know how it goes......jack of all trades but a master of none lol Commented Feb 2, 2012 at 21:02
47

I think this will help you better

Person p = new Person("Bruce", "Willis");
Person p1 = new Person("Tom", "Hanks");
Person p2 = new Person("Nicolas", "Cage");
Person p3 = new Person("John", "Travolta");
ArrayList<Person> list = new ArrayList<Person>();
list.add(p);
list.add(p1);
list.add(p2);
list.add(p3);
Collections.sort(list, new Comparator() {
 @Override
 public int compare(Object o1, Object o2) {
 Person p1 = (Person) o1;
 Person p2 = (Person) o2;
 return p1.getFirstName().compareToIgnoreCase(p2.getFirstName());
 }
});
Ziem
6,7078 gold badges57 silver badges86 bronze badges
answered Feb 2, 2012 at 9:39
0
34

Now no need to Boxing (i.e no need to Creating OBJECT using new Operator use valueOf insted with compareTo of Collections.Sort..)

1)For Ascending order

Collections.sort(temp, new Comparator<XYZBean>() 
{
 @Override
 public int compare(XYZBean lhs, XYZBean rhs) {
 return Integer.valueOf(lhs.getDistance()).compareTo(rhs.getDistance());
 }
 });

1)For Deascending order

Collections.sort(temp, new Comparator<XYZBean>() 
{
 @Override
 public int compare(XYZBean lhs, XYZBean rhs) {
 return Integer.valueOf(rhs.getDistance()).compareTo(lhs.getDistance());
 }
 });
answered Sep 18, 2015 at 15:24
3
  • Someone up above reccommended your answer for comparing integer values. However, and even I am gonna try your style anyway, I wonder: why you convert to Integer the first value, but not the second one? Will it work like this anyway? The compareTo already has an "under the hood" conversion of the parameter, or this was just a mistake? Commented Apr 14, 2023 at 6:03
  • After trying it myself, I think I know why: maybe the input for the Comparator are just int, which by itself doesn't have the compareTo method... so, if I didn't overlook anything, it was just because of that, right? So, after applying your code, Android Studio just reccommended me to replace it with Integer.compare( rhs.getDistance(), lhs.getDistance() )... doesn't it look cleaner this way? I still have to test this though... Commented Apr 14, 2023 at 6:22
  • But well, this answer is 8 years old already... perhaps this suggestion of mine was not an option with the latest API levels of those days... Commented Apr 14, 2023 at 6:29
7

It's very easy for Kotlin!

listToBeSorted.sortBy { it.distance }

answered Dec 29, 2018 at 15:20
0
2

You can compare two String by using this.

Collections.sort(contactsList, new Comparator<ContactsData>() {
 @Override
 public int compare(ContactsData lhs, ContactsData rhs) {
 char l = Character.toUpperCase(lhs.name.charAt(0));
 if (l < 'A' || l > 'Z')
 l += 'Z';
 char r = Character.toUpperCase(rhs.name.charAt(0));
 if (r < 'A' || r > 'Z')
 r += 'Z';
 String s1 = l + lhs.name.substring(1);
 String s2 = r + rhs.name.substring(1);
 return s1.compareTo(s2);
 }
 });

And Now make a ContactData Class.

public class ContactsData {
public String name;
public String id;
public String email;
public String avatar; 
public String connection_type;
public String thumb;
public String small;
public String first_name;
public String last_name;
public String no_of_user;
public int grpIndex;
public ContactsData(String name, String id, String email, String avatar, String connection_type)
{
 this.name = name;
 this.id = id;
 this.email = email;
 this.avatar = avatar;
 this.connection_type = connection_type;
}
}

Here contactsList is :

public static ArrayList<ContactsData> contactsList = new ArrayList<ContactsData>();
Vishal Chhodwani
2,5775 gold badges30 silver badges40 bronze badges
answered Oct 16, 2014 at 12:28
1
  • this places names starting from numbers (i.e 1gbfilename) on bottom. how they can be placed at top? Commented Mar 5, 2021 at 11:03
2

For Kotlin, you can use this function

fun sortList(list: List<YourCustomPOJOClass?>) {
 //descending
 Collections.sort(
 list
 ) { o1, o2 -> Integer.valueOf(o1!!.intValueXYZ!!).compareTo(o2!!.intValueXYZ!!) }
// //ascending
// Collections.sort(
// list
// ) { o1, o2 -> Integer.valueOf(o2!!.intValueXYZ!!).compareTo(o1!!.intValueXYZ!!) }
}

and just call it in your activity or fragment by

sortList(list)
answered May 31, 2020 at 8:45
2

Person Model Class

 class Person {
 int id;
 String name;
 String fatherName;
 public Person(int id, String name, String fatherName) {
 this.id = id;
 this.name = name;
 this.fatherName = fatherName;
 }
 
 }

Sorting

class SORT_BY_ID implements Comparator<Person> {
 public int compare(Person a, Person b)
 {
 return a.id - b.id;
 }
 }

Usage

 ArrayList<Person> personArrayList = new ArrayList<Person>();
 personArrayList.add(new Person(111, "bb", "oakla"));
 personArrayList.add(new Person(131, "aa", "fast"));
 personArrayList.add(new Person(121, "cccc", "paokla"));
 System.out.println("Before Sorted Array list of PErson");
 for (int i=0; i<personArrayList.size(); i++)
 System.out.println(personArrayList.get(i));
 Collections.sort(personArrayList, new SORT_BY_ID());
 System.out.println("After Sorted ");
 for (int i=0; i<personArrayList.size(); i++)
 System.out.println(personArrayList.get(i));
answered Sep 9, 2021 at 18:05
1
  • same answer is already given. You can also see different different approaches too. Commented Sep 9, 2021 at 20:52
1

"Android-java" is here by no means different than "normal java", so yes Collections.sort() would be a good approach.

answered Feb 2, 2012 at 9:32
1
  • 1
    But how do I make it sort by a value within the object. Thats what Im stuck on. Commented Feb 2, 2012 at 9:38
1
public class DateComparator implements Comparator<Marker> {
 @Override
 public int compare(Mark lhs, Mark rhs) {
 Double distance = Double.valueOf(lhs.getDistance());
 Double distance1 = Double.valueOf(rhs.getDistance());
 if (distance.compareTo(distance1) < 0) {
 return -1;
 } else if (distance.compareTo(distance1) > 0) {
 return 1;
 } else {
 return 0;
 }
 }
}
ArrayList(Marker) arraylist;

How To use:

Collections.sort(arraylist, new DateComparator());
Ziem
6,7078 gold badges57 silver badges86 bronze badges
answered Aug 8, 2013 at 13:08
1

Model Class:

public class ToDoModel implements Comparable<ToDoModel> {
 private String id;
 private Date taskDate;
 public String getId() {
 return id;
 }
 public void setId(String id) {
 this.id = id;
 }
 public Date getTaskDate() {
 return taskDate;
 }
 public void setTaskDate(Date taskDate) {
 this.taskDate = taskDate;
 }
 @Override
 public int compareTo(ToDoModel another) {
 return getTaskDate().compareTo(another.getTaskDate()); 
 }
}

Now set data in ArrayList

for (int i = 0; i < your_array_length; i++) {
 ToDoModel tm = new ToDoModel();
 tm.setId(your_id);
 tm.setTaskDate(your_date);
 mArrayList.add(tm);
}

Now Sort ArrayList

Collections.sort(toDoList);

Summary: It will sort your data datewise

Ziem
6,7078 gold badges57 silver badges86 bronze badges
answered Apr 28, 2015 at 11:56
0

Either make a Comparator that can compare your objects, or if they are all instances of the same class, you can make that class implement Comparable. You can then use Collections.sort() to do the actual sorting.

answered Feb 2, 2012 at 9:35
3
  • I went ahead and implemented Comparable in my class but and created a method to call sort on the list when i need to have it sorted but how do I sort it by a value with in the object? Commented Feb 2, 2012 at 9:42
  • The compareTo()-method is where you do the comparison. A little googling gave several detailed examples on how to use it, here is one of them: javadeveloper.co.in/java-example/java-comparable-example.html Commented Feb 2, 2012 at 9:45
  • I set up a method similar to the example however I get an error stating I cant use compareTo on a cast double. It seems like for what ever reason, what Im doing it doesnt like. Cannot invoke compareTo(double) on the primitive type double. Ill add my code up above to show what I mean Commented Feb 2, 2012 at 20:56
0

I am using this code:

Collections.sort(groupMemberList, new Comparator<GroupMember>() {
 @Override
 public int compare(GroupMember o1, GroupMember o2) {
 return Long.valueOf(o2.getStatus()).compareTo(Long.valueOf(o1.getStatus()));
}
 @Override
 public boolean equals(Object obj) {
 return false;
 }

});

0

When sorting a view model you can sort very easily, even with multiple elements if you create a comparator.

// Create the comparator
Comparator<NewsViewModel> sortByDateTime = Comparator.comparing(NewsViewModel::getNewsDate)
 .thenComparing(NewsViewModel::getNewsTime);
// Sort on date, then on time
Collections.sort(newsList, sortByDateTime);
// And even reverse the list afterwards
Collections.reverse(newsList);
answered Jan 9, 2023 at 13:06
-1

I have a listview which shows the Information about the all clients I am sorting the clients name using this custom comparator class. They are having some extra lerret apart from english letters which i am managing with this setStrength(Collator.SECONDARY)

 public class CustomNameComparator implements Comparator<ClientInfo> {
 @Override
 public int compare(ClientInfo o1, ClientInfo o2) { 
 Locale locale=Locale.getDefault();
 Collator collator = Collator.getInstance(locale);
 collator.setStrength(Collator.SECONDARY);
 return collator.compare(o1.title, o2.title);
 }
}
PRIMARY strength: Typically, this is used to denote differences between base characters (for example, "a" < "b"). It is the strongest difference. For example, dictionaries are divided into different sections by base character. 
SECONDARY strength: Accents in the characters are considered secondary differences (for example, "as" < "às" < "at"). Other differences between letters can also be considered secondary differences, depending on the language. A secondary difference is ignored when there is a primary difference anywhere in the strings. 
TERTIARY strength: Upper and lower case differences in characters are distinguished at tertiary strength (for example, "ao" < "Ao" < "aò"). In addition, a variant of a letter differs from the base form on the tertiary strength (such as "A" and "A"). Another example is the difference between large and small Kana. A tertiary difference is ignored when there is a primary or secondary difference anywhere in the strings. 
IDENTICAL strength: When all other strengths are equal, the IDENTICAL strength is used as a tiebreaker. The Unicode code point values of the NFD form of each string are compared, just in case there is no difference. For example, Hebrew cantellation marks are only distinguished at this strength. This strength should be used sparingly, as only code point value differences between two strings are an extremely rare occurrence. Using this strength substantially decreases the performance for both comparison and collation key generation APIs. This strength also increases the size of the collation key. 
**Here is a another way to make a rule base sorting if u need it just sharing**
/* String rules="< å,Å< ä,Ä< a,A< b,B< c,C< d,D< é< e,E< f,F< g,G< h,H< ï< i,I"+"< j,J< k,K< l,L< m,M< n,N< ö,Ö< o,O< p,P< q,Q< r,R"+"< s,S< t,T< ü< u,U< v,V< w,W< x,X< y,Y< z,Z";
 RuleBasedCollator rbc = null;
 try {
 rbc = new RuleBasedCollator(rules);
 } catch (ParseException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
 }
 String myTitles[]={o1.title,o2.title};
 Collections.sort(Arrays.asList(myTitles), rbc);*/
Soner Gönül
99k103 gold badges223 silver badges375 bronze badges
answered Sep 19, 2013 at 6:48

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.