Sort ArrayList android

DZone > Java Zone > Different Approaches to Sorting Elements of an ArrayList in Java

Different Approaches to Sorting Elements of an ArrayList in Java

Learn different approaches for sorting elements of an ArrayList. One using Comparable and the other using Comparator.

by
John Thompson
·
Nov. 01, 15 · Java Zone · Tutorial
Like (24)
Comment
Save
Tweet
554.51K Views

ArrayListis one of the most commonly used collection classes of the Java Collection Framework because of the functionality and flexibility it provides.ArrayListis aListimplementation that internally implements a dynamic array to store elements. Therefore, anArrayListcan dynamically grow and shrink as you add and remove elements to and from it. It is likely that you have usedArrayList, therefore I will skip the basics. If you are not familiar withArrayListyet, you can go through its API documentationhere, which is very descriptive and easy to understand to perform basic operations onArrayList.

In this post, I will discuss one of the most important operation onArrayListthat you will most likely require implementing during enterprise application development. Its sorting the elements of anArrayList.

Sorting an ArrayList of String Objects

Consider anArrayListthat stores country names asStringobjects. To sort theArrayList, you need to simply call theCollections.sort()method passing theArrayListobject populated with country names. This method will sort the elements (country names) of theArrayListusing natural ordering (alphabetically in ascending order). Letss write some code for it.

SortArrayListAscendingDescending.java

package guru.springframework.blog.sortarraylist.ascendingdescending; import java.util.ArrayList; import java.util.Collections; public class SortArrayListAscendingDescending { private ArrayList arrayList; public SortArrayListAscendingDescending(ArrayList arrayList) { this.arrayList = arrayList; } public ArrayList getArrayList() { return this.arrayList; } public ArrayList sortAscending() { Collections.sort(this.arrayList); return this.arrayList; } public ArrayList sortDescending() { Collections.sort(this.arrayList, Collections.reverseOrder()); return this.arrayList; } }

In the class above, we initialized anArrayListobject in the constructor. In thesortAscending()method, we called theCollections.sort()method passing the initializedArrayListobject and returned the sortedArrayList. In thesortDescending()method we called the overloadedCollections.sort()method to sort the elements in descending order. This version ofCollections.sort()accepts theArrayListobject as the first parameter and aComparatorobject that theCollections.reverseOrder()method returns as the second parameter. We will come toComparatora bit later. To test the sorting functionality, we will write some test code.

SortArrayListAscendingDescendingTest.java

package guru.springframework.blog.sortarraylist.ascendingdescending; import org.junit.Test; import java.util.ArrayList; import static org.junit.Assert.*; public class SortArrayListAscendingDescendingTest { @Test public void testSortAscendingDescending() throws Exception { ArrayList countryList = new ArrayList<>(); countryList.add("France"); countryList.add("USA"); countryList.add("India"); countryList.add("Spain"); countryList.add("England"); SortArrayListAscendingDescending sortArrayList = new SortArrayListAscendingDescending(countryList); ArrayList unsortedArrayList = sortArrayList.getArrayList(); System.out.println("Unsorted ArrayList: " + unsortedArrayList); ArrayList sortedArrayListAscending = sortArrayList.sortAscending(); System.out.println("Sorted ArrayList in Ascending Order : " + sortedArrayListAscending); ArrayList sortedArrayListDescending = sortArrayList.sortDescending(); System.out.println("Sorted ArrayList in Descending Order: " + sortedArrayListDescending); } }


In the test code above, we created aArrayListobject and added fiveStringobjects that represent the names of five countries to it. We then called thegetArrayList(),sortAscending(), andsortDescending()methods and printed out theArrayListobjects that the methods return.

The output is this.

------------------------------------------------------- T E S T S ------------------------------------------------------- Running guru.springframework.blog.sortarraylist.ascendingdescending.SortArrayListAscendingDescendingTest Unsorted ArrayList: [France, USA, India, Spain, England] Sorted ArrayList in Ascending Order : [England, France, India, Spain, USA] Sorted ArrayList in Descending Order: [USA, Spain, India, France, England] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec - in guru.springframework.blog.sortarraylist.ascendingdescending.SortArrayListAscendingDescendingTest

At this point, it might appear that sorting elements of anArrayListis very simple. We only need to call theCollections.sort()method passing theArrayListobject whose elements needs to be sorted. But, there is more to sortingArrayListsas you encounter additional scenarios.

TheCollections.sort()method sortsArrayListelements or elements of any otherListimplementation provided the elements are comparable. What this means programmatically is that the classes of the elements need to implement theComparableinterface of thejava.langpackage. As theStringclass implements theComparableinterface, we were able to sort theArrayListof country names. Some other classes standard to Java whichimplement theComparableinterface includethe primitive wrapper classes, such asInteger,Short,Double,Float, andBoolean.BigInteger,BigDecimal,File, andDateare also examples of classes that implementComparable.

Sorting an ArrayList using Comparable

Comparableis an interface with a singlecompareTo()method. An object of a class implementingComparableis capable of comparing itself with another object of the same type. The class implementingComparableneeds to override thecompareTo()method. This method accepts an object of the same type and implements the logic for comparingthis objectwith the one passed tocompareTo(). ThecompareTo()method returns the comparison result as an integer that has the following meanings:

  • A positive value indicates thatthis objectis greater than the object passed tocompareTo().
  • A negative value indicates thatthis objectis less than the object passed tocompareTo().
  • The value zero indicates that both the objects are equal.

Lets take an example of aJobCandidateclass whose objects we want to store in aArrayListand later sort them. TheJobCandidateclass has three fields:nameandgenderof typeStringandagethat is an integer. We want to sortJobCandidateobjects stored in theArrayListbased on theagefield. To do so, we will need to write theJobCandidateclass to implementComparableand override thecompareTo()method.

The code of theJobCandidateclass is this.

JobCandidate.java

package guru.springframework.blog.sortarraylist.comparable; public class JobCandidate implements Comparable { private String name; private String gender; private int age; public JobCandidate(String name, String gender, int age) { this.name = name; this.gender = gender; this.age = age; } public String getName() { return name; } public String getGender() { return gender; } public int getAge() { return age; } @Override public int compareTo(JobCandidate candidate) { return (this.getAge() < candidate.getAge() ? -1 : (this.getAge() == candidate.getAge() ? 0 : 1)); } @Override public String toString() { return " Name: " + this.name + ", Gender: " + this.gender + ", age:" + this.age; } }

In the overriddencompareTo()method of theJobCandidateclass above, we implemented the comparison logic based on theagefield. I have seen many programmers restoring to the shortcut version of returning the comparison result asreturn (this.getAge() - candidate.getAge());. Although using this return statement might appear tempting and will not anyhow affect our example, my advice is to stay away from it. Imagine, the result of comparing integer values where one or both of them are negative values. It canlead to bugs that will make your application behave erratically and more than that, such bugs being subtle, are extremely difficult to detect especially in large enterprise applications. Next, well write a helper class whichwill sortArrayListobjects containingJobCandidateelements for clients.

JobCandidateSorter.java

package guru.springframework.blog.sortarraylist.comparable; import java.util.ArrayList; import java.util.Collections; public class JobCandidateSorter { ArrayList jobCandidate = new ArrayList<>(); public JobCandidateSorter(ArrayList jobCandidate) { this.jobCandidate = jobCandidate; } public ArrayList getSortedJobCandidateByAge() { Collections.sort(jobCandidate); return jobCandidate; } }


In theJobCandidateSorterclass we initialized aArrayListobject that client will pass through the constructor while instantiatingJobCandidateSorter. We then wrote thegetSortedJobCandidateByAge()method. In this method, we calledCollections.sort()passing the initializedArrayList. Finally, we returned back the sortedArrayList.

Next, we will write a test class to test our code.

JobCandidateSorterTest.java

package guru.springframework.blog.sortarraylist.comparable; import org.junit.Test; import java.lang.reflect.Array; import java.util.ArrayList; import static org.junit.Assert.*; public class JobCandidateSorterTest { @Test public void testGetSortedJobCandidateByAge() throws Exception { JobCandidate jobCandidate1 = new JobCandidate("Mark Smith", "Male", 26); JobCandidate jobCandidate2 = new JobCandidate("Sandy Hunt", "Female", 23); JobCandidate jobCandidate3 = new JobCandidate("Betty Clark", "Female", 20); JobCandidate jobCandidate4 = new JobCandidate("Andrew Styne", "Male", 24); ArrayList jobCandidateList = new ArrayList<>(); jobCandidateList.add(jobCandidate1); jobCandidateList.add(jobCandidate2); jobCandidateList.add(jobCandidate3); jobCandidateList.add(jobCandidate4); JobCandidateSorter jobCandidateSorter = new JobCandidateSorter(jobCandidateList); ArrayList sortedJobCandidate = jobCandidateSorter.getSortedJobCandidateByAge(); System.out.println("-----Sorted JobCandidate by age: Ascending-----"); for (JobCandidate jobCandidate : sortedJobCandidate) { System.out.println(jobCandidate); } } }

In the test class above, we created fourJobCandidateobjects and added them to anArrayList. We then instantiated theJobCandidateSorterclass passing ourArrayListto its constructor. Finally, we called thegetSortedJobCandidateByAge()method ofJobCandidateSorterand printed out the sortedArrayListthat the method returns. The output on running the test is this.

------------------------------------------------------- T E S T S ------------------------------------------------------- Running guru.springframework.blog.sortarraylist.comparable.JobCandidateSorterTest -----Sorted JobCandidate by age: Ascending----- Name: Betty Clark, Gender: Female, age:20 Name: Sandy Hunt, Gender: Female, age:23 Name: Andrew Styne, Gender: Male, age:24 Name: Mark Smith, Gender: Male, age:26 Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.003 sec - in guru.springframework.blog.sortarraylist.comparable.JobCandidateSorterTest

SortingArrayListusingComparableis a common approach. But, you need tobe aware of certain constraints. The class whose object you want to sort must implementComparableand override thecompareTo()method. This essentially means you would only be able to compare the objects based on one field (which wasagein our example). What if the requirementsstate you need tobe able to sortJobCandidateobjects by name and alsoby age?Comparableis not the solution. In addition, comparison logic is part of the class whose objects needs to be compared, which eliminates any chance of reusability of the comparison logic. Java addresses such comparison requirements used in sorting by providing theComparatorinterface in thejava.utilpackage.

Sorting an ArrayList using Comparator

TheComparatorinterface similar to theComparableinterface provides a single comparison method namedcompare(). However, unlike thecompareTo()method ofComparable, thecompare()method takes two different objects of the same type for comparison.
We will useComparatorto sort objects of the sameJobCandidateclass we used earlier but with few differences. We will allow sortingJobCandidateobjects both by name and age by implementingComparatoras anonymous inner classes.

Here is the code of theJobCandidateclass usingComparator.

JobCandidate.java

package guru.springframework.blog.sortarraylist.comparator; import java.util.Comparator; public class JobCandidate { private String name; private String gender; private int age; public JobCandidate(String name, String gender, int age) { this.name = name; this.gender = gender; this.age = age; } public String getName() { return name; } public String getGender() { return gender; } public int getAge() { return age; } public static Comparator ageComparator = new Comparator() { @Override public int compare(JobCandidate jc1, JobCandidate jc2) { return (jc2.getAge() < jc1.getAge() ? -1 : (jc2.getAge() == jc1.getAge() ? 0 : 1)); } }; public static Comparator nameComparator = new Comparator() { @Override public int compare(JobCandidate jc1, JobCandidate jc2) { return (int) (jc1.getName().compareTo(jc2.getName())); } }; @Override public String toString() { return " Name: " + this.name + ", Gender: " + this.gender + ", age:" + this.age; } }

In the class above, from Line 29 Line 35, we wrote an anonymous class and implemented thecompare()method that will allow sortingJobCandidateobjects by age in descending order. From Line 37 Line 42, we again wrote an anonymous class and implemented thecompare()method that will allow sortingJobCandidateobjects by name in ascending order. We will now write a class that will sort the elements of theArrayListfor clients.

JobCandidateSorter.java

package guru.springframework.blog.sortarraylist.comparator; import java.util.ArrayList; import java.util.Collections; public class JobCandidateSorter { ArrayList jobCandidate = new ArrayList<>(); public JobCandidateSorter(ArrayList jobCandidate) { this.jobCandidate = jobCandidate; } public ArrayList getSortedJobCandidateByAge() { Collections.sort(jobCandidate, JobCandidate.ageComparator); return jobCandidate; } public ArrayList getSortedJobCandidateByName() { Collections.sort(jobCandidate, JobCandidate.nameComparator); return jobCandidate; } }


In the class above, we wrote thegetSortedJobCandidateByAge()method. In this method we called the overloaded version ofCollections.sort()passing theArrayListobject to be sorted and theComparatorobject that compares age. In thegetSortedJobCandidateByName()method, we again called the overloaded version ofCollections.sort()passing theArrayListobject to be sorted and theComparatorobject to compare names.

Lets write a test class to test our code.

JobCandidateSorterTest.java

package guru.springframework.blog.sortarraylist.comparator; import guru.springframework.blog.sortarraylist.comparator.JobCandidate; import guru.springframework.blog.sortarraylist.comparator.JobCandidateSorter; import org.junit.Before; import org.junit.Test; import java.util.ArrayList; import static org.junit.Assert.*; public class JobCandidateSorterTest { JobCandidateSorter jobCandidateSorter; @Before public void setUp() throws Exception { JobCandidate jobCandidate1 = new JobCandidate("Mark Smith", "Male", 26); JobCandidate jobCandidate2 = new JobCandidate("Sandy Hunt", "Female", 23); JobCandidate jobCandidate3 = new JobCandidate("Betty Clark", "Female", 20); JobCandidate jobCandidate4 = new JobCandidate("Andrew Styne", "Male", 24); ArrayList jobCandidateList = new ArrayList<>(); jobCandidateList.add(jobCandidate1); jobCandidateList.add(jobCandidate2); jobCandidateList.add(jobCandidate3); jobCandidateList.add(jobCandidate4); jobCandidateSorter = new JobCandidateSorter(jobCandidateList); } @Test public void testGetSortedJobCandidateByAge() throws Exception { System.out.println("-----Sorted JobCandidate by age: Descending-----"); ArrayList sortedJobCandidate = jobCandidateSorter.getSortedJobCandidateByAge(); for (JobCandidate jobCandidate : sortedJobCandidate) { System.out.println(jobCandidate); } } @Test public void testGetSortedJobCandidateByName() throws Exception { System.out.println("-----Sorted JobCandidate by name: Ascending-----"); ArrayList sortedJobCandidate = jobCandidateSorter.getSortedJobCandidateByName(); for (JobCandidate jobCandidate : sortedJobCandidate) { System.out.println(jobCandidate); } } }


In the test class we populatedJobCandidateobjects in anArrayListand created aJobCandidateSorterobject in the JUnitsetup()method annotated with@Before. If you are new to JUnit, you can refer my post covering JUnit annotations (Part of a series on unit testing with JUnit)here. In thetestGetSortedJobCandidateByAge()test method we called thegetSortedJobCandidateByAge()method and printed out the sortedArrayListthat the method returns. In thetestGetSortedJobCandidateByName()test method, we called thegetSortedJobCandidateByName()method and printed out the sortedArrayListthat the method returns. The output of the test is this.

------------------------------------------------------- T E S T S ------------------------------------------------------- Running guru.springframework.blog.sortarraylist.comparator.JobCandidateSorterTest -----Sorted JobCandidate by name: Ascending----- Name: Andrew Styne, Gender: Male, age:24 Name: Betty Clark, Gender: Female, age:20 Name: Mark Smith, Gender: Male, age:26 Name: Sandy Hunt, Gender: Female, age:23 -----Sorted JobCandidate by age: Descending----- Name: Mark Smith, Gender: Male, age:26 Name: Andrew Styne, Gender: Male, age:24 Name: Sandy Hunt, Gender: Female, age:23 Name: Betty Clark, Gender: Female, age:20 Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.023 sec - in guru.springframework.blog.sortarraylist.comparator.JobCandidateSorterTest

Conclusion

In this post we looked at different approaches of sorting elements ofArrayList. One usingComparableand the other usingComparator. The approach to choose has always been a cause of confusion for programmers. What you should essentially remember is that aComparableobject can say I can compare myself with another object while aComparatorobject can say I can compare two different objects. You cannot say that one interface is better than the other. The interface you choose depends upon the functionality you needto achieve.




If you enjoyed this article and want to learn more about Java Collections, check out this collection of tutorials and articleson all things Java Collections.

Topics:
java, sorting

Published at DZone with permission of John Thompson, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

  • Importance of Data Discovery in Data Mesh Architecture
  • A Site Reliability Engineers Guide to the Holiday Season
  • How To Insert, Retrieve, and Query Data From Amazon Dynamo DB in Mule 4
  • The First Annual Recap From JPA Buddy

Comments

Java Partner Resources