I'm a beginner in Java. Please suggest which collection(s) can/should be used for maintaining a sorted list in Java. I have tried Map
and Set
, but they weren't what I was looking for.

- 9,550
- 4
- 44
- 49
21 Answers
This comes very late, but there is a class in the JDK just for the purpose of having a sorted list. It is named (somewhat out of order with the other Sorted*
interfaces) "java.util.PriorityQueue
". It can sort either Comparable<?>
s or using a Comparator
.
The difference with a List
sorted using Collections.sort(...)
is that this will maintain a partial order at all times, with O(log(n)) insertion performance, by using a heap data structure, whereas inserting in a sorted ArrayList
will be O(n) (i.e., using binary search and move).
However, unlike a List
, PriorityQueue
does not support indexed access (get(5)
), the only way to access items in a heap is to take them out, one at a time (thus the name PriorityQueue
).

- 12,622
- 6
- 51
- 57

- 9,497
- 6
- 31
- 33
-
4imo this answer deserves more upvotes since it points out the only Collection that has the capability in JDK – nimcap Jul 02 '10 at 12:09
-
1@Thilo: Right, but since the elements' indexes change with every modification, it is probably not needed anyway – nimcap Oct 27 '10 at 11:23
-
98From the Javadoc: "The Iterator provided in method iterator() is not guaranteed to traverse the elements of the PriorityQueue in any particular order." – Christoffer Hammarström Mar 02 '11 at 14:37
-
@Christoffer: so what's the point of keeping a list sorted if it cannot be accessed in a sorted way? – giraff Jun 29 '11 at 09:05
-
10@giraff: a priority queue is just that, a data structure that is very efficient at keeping a priority queue. You can poll from the front and get the data items in sorted order. However heaps don't maintain a total order of elements internally (that's why they are so efficient), so there is no way of accessing elements in order without executing the poll operation. – Martin Probst Jul 01 '11 at 16:42
-
2@chrispy it depends a bit on what you exactly want to do achieve with your data structure. Heaps are an efficient way to maintain a list of items and retrieve them in an ordered fashion later - using the iterator doesn't work, but if you poll from it, you will get your data in order. Retrieval is destructive, but that could still be ok in many cases. So I think this answer is good. – Martin Probst Jan 15 '12 at 21:18
-
@chrispy It's still the best answer to the question. The only real option, of course, is to not use the JDK for this task, hence the real question is: Why oh why for crying out loud do the base libraries for collections not contain something so trivial? – M.Stramm May 31 '12 at 12:15
-
@m-stramm It's been edited since my request was made, and is now at least pointing out the problem above-the-fold. – Alice Purcell Jun 07 '12 at 08:59
-
2Your answer is misleading. PriorityQueue is NOT a list. A list maintains a determined sequence and has indexed access. Else SortedSet would do the same job just as fine. – BlueM Apr 16 '13 at 12:52
-
4@MartinProbst Please rectify your answer to CLEARLY indicate that that collection CAN NOT BE ITERATED in the expected order. As many have said, this is extremelly misleading! – Jorge Galvão Feb 15 '14 at 20:10
-
@MartinProbst I read the entire thing here and now left with confusion? Have you rectified this answer as requested by Jorge Galvao on Feb 15 '14? – Nirmal Jun 23 '15 at 22:54
-
@chrispy does your edit make this answer ok for using this answer in the present day? – Nirmal Jun 23 '15 at 22:55
-
@user3320018 Yes, if the proviso in the last paragraph is not an issue for you. – Alice Purcell Aug 23 '15 at 15:43
-
this is a misleading answer. PriorityQueue is a heap and does not 'maintain a sorted list'. the only way to get the sorted list from it is to drain the PriorityQueue which is destructive and is not the best or even feasible way. – averasko Apr 17 '20 at 14:25
TreeMap and TreeSet will give you an iteration over the contents in sorted order. Or you could use an ArrayList and use Collections.sort() to sort it. All those classes are in java.util

- 342,105
- 78
- 482
- 720
-
30There are two major drawbacks to this though, the first being that a Set can not have duplicates. The second is that if you use a list and Collections.sort(), you tend to be constantly sorting huge lists and gives poor performance. Sure you can use a 'dirty' flag, but it's not quite the same. – Jeach Dec 06 '10 at 21:52
-
That brings to a question whether do we have an option in Java which allows dupliactes and also give performances similar to Set (Balanced Binary Tree) – mankadnandan Oct 25 '17 at 14:13
-
1Another problem with SortedSet/TreeMap is they won't work even if your key is unique but your Comparator value for the different keys is same. A TreeSet((UniqueKey1, UniqueKey2) -> Comparator.compare(otherValueLookup.get(key1), otherValueLookup.get(key2)) This will fail sorting as it won't add values if otherValue are same! Conclusion: TreeSet/TreeMap won't add values if two keys are different but equal according to Comparator – kisna Oct 03 '20 at 23:05
-
1Need to add that we can still use TreeSet/TreeMap, the work around is to create a Randomizer if keys are same: ThreadLocalRandom r = ThreadLocalRandom.current(); boolean randomBoolean = r.nextBoolean(); if (key1.equals(key2)) { // ** If they are equal, do a RANDOM comparator ** return randomBoolean ? 1 : -1; } else { return key1.compareTo(key2); } – kisna Oct 03 '20 at 23:35
-
"RANDOM comparator" is a bad idea and will lead to strange behaviors. Your comparator should be consistent for the same instances. You can compare based on a UUID though, see https://stackoverflow.com/q/73925525/7424948 – Ricola Oct 02 '22 at 14:47
If you want to maintain a sorted list which you will frequently modify (i.e. a structure which, in addition to being sorted, allows duplicates and whose elements can be efficiently referenced by index), then use an ArrayList but when you need to insert an element, always use Collections.binarySearch() to determine the index at which you add a given element. The latter method tells you the index you need to insert at to keep your list in sorted order.

- 21,615
- 7
- 62
- 83
-
11n inserts will be O(n^2). A TreeSet will give you cleaner code and O(n log n). OTOH, for *infrequent* modification binary search of an array will be faster and use less memory (so less GC overhead). – Tom Hawtin - tackline Jan 06 '09 at 13:45
-
To keep the code clean and still allow for duplicates it would be easy enough to create a SortedList class that inserts values in sorted order. – Mr. Shiny and New 安宇 Jan 06 '09 at 14:07
-
This is a way better answer than the most upvoted answer, imo, if you can live with the caveat mentioned by @TomHawtin-tackline. That the iterator works as expected is crucial for most cases. – DuneCat Oct 11 '12 at 12:09
-
Incidentally, Tom is right on that specific behaviour: a tree set will give you more efficient modification. But a tree set isn't a list (in the strictest sense of having elements referenced by index and allowing duplicates) and the poster said they wanted a list. – Neil Coffey Oct 11 '12 at 17:52
-
-
@NeilCoffey if list allows duplicates, then `Collections.binarySearch` is not very reliable [imo](http://stackoverflow.com/questions/15606219/java-collection-binarysearch-not-working-properly?rq=1) – nawfal Jun 16 '14 at 07:06
-
@nawfal - So that essentially depends on your application, I think. The behaviour is that the order of objects "equal" to one another in the list will be undefined, but other objects around them will be in order. You need to decide if that's appropriate to your application or not. – Neil Coffey Feb 20 '15 at 00:49
Use Google Guava's TreeMultiset class. Guava has a spectacular collections API.
One problem with providing an implementation of List that maintains sorted order is the promise made in the JavaDocs of the add()
method.

- 16,038
- 10
- 74
- 104

- 828
- 1
- 7
- 11
-
-
7+1 for mentioning the requirement that a `List` always adds at the end. – Roland Illig Jun 27 '11 at 13:24
-
2Note that TreeMultiSet still does not allow duplicate elements (elements that compareTo() returns 0, not equals() check). If you tend to add more than one item of same priority, it will only increase the count of the first added one, discarding other and effectively being a good Counting Bag implementation. – bekce Sep 28 '12 at 17:59
-
10Not necessarily; sets cannot have duplicate values. It depends on the OP's requirements. – Zach Langley Jan 06 '09 at 13:20
There are a few options. I'd suggest TreeSet if you don't want duplicates and the objects you're inserting are comparable.
You can also use the static methods of the Collections class to do this.
See Collections#sort(java.util.List) and TreeSet for more info.

- 20,267
- 14
- 135
- 196

- 4,056
- 3
- 24
- 26
If you just want to sort a list, use any kind of List and use Collections.sort(). If you want to make sure elements in the list are unique and always sorted, use a SortedSet.

- 18,494
- 8
- 53
- 74
The most efficient way to implement a sorted list like you want would be to implement an indexable skiplist as in here: Wikipedia: Indexable skiplist. It would allow to have inserts/removals in O(log(n)) and would allow to have indexed access at the same time. And it would also allow duplicates.
Skiplist is a pretty interesting and, I would say, underrated data structure. Unfortunately there is no indexed skiplist implementation in Java base library, but you can use one of open source implementations or implement it yourself. There are regular Skiplist implementations like ConcurrentSkipListSet and ConcurrentSkipListMap

- 568
- 6
- 9
What I have done is implement List having a internal instance with all the methods delegated.
public class ContactList implements List<Contact>, Serializable {
private static final long serialVersionUID = -1862666454644475565L;
private final List<Contact> list;
public ContactList() {
super();
this.list = new ArrayList<Contact>();
}
public ContactList(List<Contact> list) {
super();
//copy and order list
List<Contact>aux= new ArrayList(list);
Collections.sort(aux);
this.list = aux;
}
public void clear() {
list.clear();
}
public boolean contains(Object object) {
return list.contains(object);
}
After, I have implemented a new method "putOrdered" which insert in the proper position if the element doesn't exist or replace just in case it exist.
public void putOrdered(Contact contact) {
int index=Collections.binarySearch(this.list,contact);
if(index<0){
index= -(index+1);
list.add(index, contact);
}else{
list.set(index, contact);
}
}
If you want to allow repeated elements just implement addOrdered instead (or both).
public void addOrdered(Contact contact) {
int index=Collections.binarySearch(this.list,contact);
if(index<0){
index= -(index+1);
}
list.add(index, contact);
}
If you want to avoid inserts you can also throw and unsupported operation exception on "add" and "set" methods.
public boolean add(Contact object) {
throw new UnsupportedOperationException("Use putOrdered instead");
}
... and also You have to be careful with ListIterator methods because they could modify your internal list. In this case you can return a copy of the internal list or again throw an exception.
public ListIterator<Contact> listIterator() {
return (new ArrayList<Contact>(list)).listIterator();
}

- 3,037
- 22
- 20
-
The problem is that this violates the `List` contract. Maybe it would be better to only implement `Collection`. And if `ContactList` is sorted, then `contains()` can be implemented using `binarySearch` as well to be more efficient. – Marcono1234 Jul 13 '19 at 16:09
TreeSet would not work because they do not allow duplicates plus they do not provide method to fetch element at specific position. PriorityQueue would not work because it does not allow fetching elements at specific position which is a basic requirement for a list. I think you need to implement your own algorithm to maintain a sorted list in Java with O(logn) insert time, unless you do not need duplicates. Maybe a solution could be using a TreeMap where the key is a subclass of the item overriding the equals method so that duplicates are allowed.

- 41
- 2
Using LambdaJ
You can try solving these tasks with LambdaJ if you are using prior versions to java 8. You can find it here: http://code.google.com/p/lambdaj/
Here you have an example:
Sort Iterative
List<Person> sortedByAgePersons = new ArrayList<Person>(persons);
Collections.sort(sortedByAgePersons, new Comparator<Person>() {
public int compare(Person p1, Person p2) {
return Integer.valueOf(p1.getAge()).compareTo(p2.getAge());
}
});
Sort with LambdaJ
List<Person> sortedByAgePersons = sort(persons, on(Person.class).getAge());
Of course, having this kind of beauty impacts in the performance (an average of 2 times), but can you find a more readable code?
Sort with java 8 using lambda expression
Collections.sort(persons, (p1, p2) -> p1.getAge().compareTo(p2.getAge()));
//or
persons.sort((p1, p2) -> p1.getAge().compareTo(p2.getAge()));

- 30,085
- 15
- 87
- 123
-
In your last example with java 8 lambda expression, how can one reverse sort? – Rajat Jun 14 '16 at 00:03
-
1@RajatShah I guess you can just do `-(p1.getAge().compareTo(p2.getAge()))` – Federico Piazza Jun 14 '16 at 00:05
-
For Set you can use TreeSet. TreeSet orders it's elements on the basis of a natural ordering or any sorting order passed to the Comparable for that particular object. For map use TreeMap. TreeMap provides the sorting over keys. To add an object as a key to the TreeMap that class should implement comparable interface which in turn forces to implement compare to() method which contains the definition of the sorting order. http://techmastertutorial.in/java-collection-impl.html

- 61
- 3
The problem with PriorityQueue is that it's backed up by an simple array, and the logic that gets the elements in order is done by the "queue[2*n+1] and queue[2*(n+1)]" thingie. It works great if you just pull from head, but makes it useless if you are trying to call the .toArray on it at some point.
I go around this problem by using com.google.common.collect.TreeMultimap, but I supply a custom Comparator for the values, wrapped in an Ordering, that never returns 0.
ex. for Double:
private static final Ordering<Double> NoEqualOrder = Ordering.from(new Comparator<Double>() {
@Override
public int compare(Double d1, Double d2)
{
if (d1 < d2) {
return -1;
}
else {
return 1;
}
}
});
This way I get the values in order when I call .toArray(), and also have duplicates.

- 3,098
- 4
- 32
- 39
What you want is a binary search tree. It maintains sorted order while offering logarithmic access for searches, removals and insertions (unless you have a degenerated tree - then it's linear). It is quite easy to implement and you even can make it implement the List interface, but then the index-access gets complicated.
Second approach is to have an ArrayList and then a bubble sort implementation. Because you are inserting or removing one element at a time, the access times for insertions and removals are linear. Searches are logarithmic and index access constant (times can get different for LinkedList). The only code you need is 5, maybe 6 lines of bubble sort.

- 8,816
- 3
- 32
- 48
You can use Arraylist and Treemap, as you said you want repeated values as well then you cant use TreeSet, though it is sorted as well, but you have to define comparator.
Sorting an ArrayList according to user defined criteria.
Model Class
class Student
{
int rollno;
String name, address;
public Student(int rollno, String name, String address)
{
this.rollno = rollno;
this.name = name;
this.address = address;
}
public String toString()
{
return this.rollno + " " + this.name + " " + this.address;
}
}
Sorting Class
class Sortbyroll implements Comparator<Student>
{
public int compare(Student a, Student b)
{
return a.rollno - b.rollno;
}
}
Main Class
class Main
{
public static void main (String[] args)
{
ArrayList<Student> ar = new ArrayList<Student>();
ar.add(new Student(111, "bbbb", "london"));
ar.add(new Student(131, "aaaa", "nyc"));
ar.add(new Student(121, "cccc", "jaipur"));
System.out.println("Unsorted");
for (int i=0; i<ar.size(); i++)
System.out.println(ar.get(i));
Collections.sort(ar, new Sortbyroll());
System.out.println("\nSorted by rollno");
for (int i=0; i<ar.size(); i++)
System.out.println(ar.get(i));
}
}
Output
Unsorted
111 bbbb london
131 aaaa nyc
121 cccc jaipur
Sorted by rollno
111 bbbb london
121 cccc jaipur
131 aaaa nyc

- 360
- 5
- 12
Why don't make it yourself?
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
class SortedList<E extends Comparable<E>> extends ArrayList<E> {
@Override
public boolean add(E e) {
int i = Collections.binarySearch(this, e);
if (i < 0) i = ~i;
super.add(i, e);
return true;
} // add(E e)
@Override
public void add(int index, E element) {
this.add(element);
} // add(int, E)
@Override
public boolean addAll(Collection<? extends E> c) {
int oldSize = this.size();
for (E element : c) this.add(element);
return oldSize != this.size();
} // addAll(Collection<? extends E>)
@Override
public boolean addAll(int index, Collection<? extends E> c) {
int oldSize = this.size();
Iterator<? extends E> it = c.iterator();
for (int i = 0; i < index; ++i) it.next();
while (it.hasNext()) this.add(it.next());
return oldSize != this.size();
} // addAll(Collection<? extends E>)
@Override
public E set(int index, E element) {
E ret = this.get(index);
this.remove(index);
this.add(element);
return ret;
} // set(int, E)
} // SortedList<E> Class
public class Solution {
public static void main(String[] args) {
Random r = new Random(1);
List<Integer> sortedList = new SortedList<>();
List<Integer> unsortedList = new ArrayList<>();
for (int i = 0; i < 50; ++i) {
int next = r.nextInt(1000);
sortedList.add(next);
unsortedList.add(next);
} // for (int i = 0; i < 50; ++i)
System.out.println("unsortedList:");
System.out.println(unsortedList);
System.out.println("\nsortedList:");
System.out.println(sortedList);
sortedList.clear();
sortedList.addAll(unsortedList);
System.out.println("\ntest for addAll(Collection) method:");
System.out.println(sortedList);
sortedList.clear();
sortedList.addAll(30, unsortedList);
System.out.println("\ntest for addAll(int, Collection) method:");
System.out.println(sortedList);
sortedList.set(0, 999);
System.out.println("\ntest for set(int, E) method:");
System.out.println(sortedList);
} // main(String[])
} // Solution Class
output:
unsortedList:
[985, 588, 847, 313, 254, 904, 434, 606, 978, 748, 569, 473, 317, 263, 562, 234, 592, 262, 596, 189, 376, 332, 310, 99, 674, 959, 298, 153, 437, 302, 205, 854, 800, 6, 363, 955, 689, 820, 75, 834, 415, 660, 477, 737, 477, 592, 220, 888, 500, 357]
sortedList:
[6, 75, 99, 153, 189, 205, 220, 234, 254, 262, 263, 298, 302, 310, 313, 317, 332, 357, 363, 376, 415, 434, 437, 473, 477, 477, 500, 562, 569, 588, 592, 592, 596, 606, 660, 674, 689, 737, 748, 800, 820, 834, 847, 854, 888, 904, 955, 959, 978, 985]
test for addAll(Collection) method:
[6, 75, 99, 153, 189, 205, 220, 234, 254, 262, 263, 298, 302, 310, 313, 317, 332, 357, 363, 376, 415, 434, 437, 473, 477, 477, 500, 562, 569, 588, 592, 592, 596, 606, 660, 674, 689, 737, 748, 800, 820, 834, 847, 854, 888, 904, 955, 959, 978, 985]
test for addAll(int, Collection) method:
[6, 75, 205, 220, 357, 363, 415, 477, 477, 500, 592, 660, 689, 737, 800, 820, 834, 854, 888, 955]
test for set(int, E) method:
[75, 205, 220, 357, 363, 415, 477, 477, 500, 592, 660, 689, 737, 800, 820, 834, 854, 888, 955, 999]

- 11
- 1
Use sort() method to sort the list as below:
List list = new ArrayList();
//add elements to the list
Comparator comparator = new SomeComparator();
Collections.sort(list, comparator);
For reference see the link: http://tutorials.jenkov.com/java-collections/sorting.html

- 3,620
- 1
- 29
- 38

- 23
- 7
Use TreeSet
which gives elements in sorted order. OR use Collection.sort()
for external sorting with Comparator()
.

- 5,613
- 10
- 39
- 51

- 1
- 1
-
TreeSet does not allow duplication of elements. Sometimes it is a desired feature, others not. Considering the OP tried the sets, I guess for the no – usr-local-ΕΨΗΕΛΩΝ Jul 27 '17 at 14:38
-
Don't be mean, point out the TreeMap too: https://docs.oracle.com/javase/10/docs/api/java/util/TreeMap.html – Haakon Løtveit Apr 23 '18 at 08:33
import java.util.TreeSet;
public class Ass3 {
TreeSet<String>str=new TreeSet<String>();
str.add("dog");
str.add("doonkey");
str.add("rat");
str.add("rabbit");
str.add("elephant");
System.out.println(str);
}

- 2,212
- 1
- 13
- 23
with Java 8 Comparator, if we want to sort list then Here are the 10 most populated cities in the world and we want to sort it by name, as reported by Time. Osaka, Japan. ... Mexico City, Mexico. ... Beijing, China. ... São Paulo, Brazil. ... Mumbai, India. ... Shanghai, China. ... Delhi, India. ... Tokyo, Japan.
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class SortCityList {
/*
* Here are the 10 most populated cities in the world and we want to sort it by
* name, as reported by Time. Osaka, Japan. ... Mexico City, Mexico. ...
* Beijing, China. ... São Paulo, Brazil. ... Mumbai, India. ... Shanghai,
* China. ... Delhi, India. ... Tokyo, Japan.
*/
public static void main(String[] args) {
List<String> cities = Arrays.asList("Osaka", "Mexico City", "São Paulo", "Mumbai", "Shanghai", "Delhi",
"Tokyo");
System.out.println("Before Sorting List is:-");
System.out.println(cities);
System.out.println("--------------------------------");
System.out.println("After Use of List sort(String.CASE_INSENSITIVE_ORDER) & Sorting List is:-");
cities.sort(String.CASE_INSENSITIVE_ORDER);
System.out.println(cities);
System.out.println("--------------------------------");
System.out.println("After Use of List sort(Comparator.naturalOrder()) & Sorting List is:-");
cities.sort(Comparator.naturalOrder());
System.out.println(cities);
}
}

- 761
- 11
- 16