Sorted collection in Java

JavaSortingCollections

Java Problem Overview


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.

Java Solutions


Solution 1 - Java

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).

Solution 2 - Java

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

Solution 3 - Java

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.

Solution 4 - Java

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.

Solution 5 - Java

You want the SortedSet implementations, namely TreeSet.

Solution 6 - Java

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.

Solution 7 - Java

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.

Solution 8 - Java

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();
}

Solution 9 - Java

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

Solution 10 - Java

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.

Solution 11 - Java

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()));

Solution 12 - Java

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[2n+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.

Solution 13 - Java

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

Solution 14 - Java

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.

Solution 15 - Java

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.

Solution 16 - Java

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

Solution 17 - Java

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

Solution 18 - Java

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);	
}

Solution 19 - Java

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);

	}

}

Solution 20 - Java

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

Solution 21 - Java

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]

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionrohanView Question on Stackoverflow
Solution 1 - JavaMartin ProbstView Answer on Stackoverflow
Solution 2 - JavaMichael BorgwardtView Answer on Stackoverflow
Solution 3 - JavajtbView Answer on Stackoverflow
Solution 4 - JavaNeil CoffeyView Answer on Stackoverflow
Solution 5 - JavacletusView Answer on Stackoverflow
Solution 6 - JavaBenMView Answer on Stackoverflow
Solution 7 - JavaGuillaumeView Answer on Stackoverflow
Solution 8 - JavaCarlos VerdesView Answer on Stackoverflow
Solution 9 - JavavladichView Answer on Stackoverflow
Solution 10 - JavaGiuseppeView Answer on Stackoverflow
Solution 11 - JavaFederico PiazzaView Answer on Stackoverflow
Solution 12 - JavaMartin KlosiView Answer on Stackoverflow
Solution 13 - JavaAvi TyagiView Answer on Stackoverflow
Solution 14 - JavaJakub ZaverkaView Answer on Stackoverflow
Solution 15 - Javauser5497526View Answer on Stackoverflow
Solution 16 - JavaShashank MungantiwarView Answer on Stackoverflow
Solution 17 - JavaHariView Answer on Stackoverflow
Solution 18 - JavaDeepica M YView Answer on Stackoverflow
Solution 19 - JavaVipul GulhaneView Answer on Stackoverflow
Solution 20 - JavaskpaikView Answer on Stackoverflow
Solution 21 - JavashiawasenahikariView Answer on Stackoverflow