223

I have a List<String> object that contains country names. How can I sort this list alphabetically?

james.garriss
  • 12,959
  • 7
  • 83
  • 96
Lennie
  • 2,429
  • 2
  • 18
  • 16

16 Answers16

252

Assuming that those are Strings, use the convenient static method sort:

Collections.sort(listOfCountryNames)
BullyWiiPlaza
  • 17,329
  • 10
  • 113
  • 185
Thilo
  • 257,207
  • 101
  • 511
  • 656
158

Solution with Collections.sort

If you are forced to use that List, or if your program has a structure like

  • Create List
  • Add some country names
  • sort them once
  • never change that list again

then Thilos answer will be the best way to do it. If you combine it with the advice from Tom Hawtin - tackline, you get:

java.util.Collections.sort(listOfCountryNames, Collator.getInstance());

Solution with a TreeSet

If you are free to decide, and if your application might get more complex, then you might change your code to use a TreeSet instead. This kind of collection sorts your entries just when they are inserted. No need to call sort().

Collection<String> countryNames = 
    new TreeSet<String>(Collator.getInstance());
countryNames.add("UK");
countryNames.add("Germany");
countryNames.add("Australia");
// Tada... sorted.

Side note on why I prefer the TreeSet

This has some subtle, but important advantages:

  • It's simply shorter. Only one line shorter, though.
  • Never worry about is this list really sorted right now becaude a TreeSet is always sorted, no matter what you do.
  • You cannot have duplicate entries. Depending on your situation this may be a pro or a con. If you need duplicates, stick to your List.
  • An experienced programmer looks at TreeSet<String> countyNames and instantly knows: this is a sorted collection of Strings without duplicates, and I can be sure that this is true at every moment. So much information in a short declaration.
  • Real performance win in some cases. If you use a List, and insert values very often, and the list may be read between those insertions, then you have to sort the list after every insertion. The set does the same, but does it much faster.

Using the right collection for the right task is a key to write short and bug free code. It's not as demonstrative in this case, because you just save one line. But I've stopped counting how often I see someone using a List when they want to ensure there are no duplictes, and then build that functionality themselves. Or even worse, using two Lists when you really need a Map.

Don't get me wrong: Using Collections.sort is not an error or a flaw. But there are many cases when the TreeSet is much cleaner.

Lena Schimmel
  • 7,203
  • 5
  • 43
  • 58
  • I don't see any advantage to using TreeSet over sort. – DJClayworth Apr 02 '09 at 14:28
  • 1
    Well TreeSet avoids accidental duplication (which may be good or bad) and it should be faster (though not by much given the size of input) and it will always be sorted rather than sorted after all the input (unless you sort the list after each insert) which may matter, but probably not. So faster.. – TofuBeer Apr 02 '09 at 14:46
  • 1
    @TofuBeer I was just clarifying this while you were doing it too. And if you really care about what's faster, have a look at http://stackoverflow.com/questions/168891/is-it-faster-to-sort-a-list-after-inserting-items-or-adding-them-to-a-sorted-list – Lena Schimmel Apr 02 '09 at 15:04
  • Brian, I like your TreeSet solution, but the code sample for the TreeSet constructor should only have one parameter, right? I.e. remove the "comp, " part – Brummo Jan 08 '11 at 19:16
  • 9
    A TreeSet will not stay sorted if the items are mutable. – Joshua Goldberg Oct 20 '11 at 22:20
  • 3
    @JoshuaGoldberg I think it will not only get un-sorted, it will also stop working correctly. At least if the mutatation of the object affects its sorting order. The tree set relies on the items being sorted to perform its tasks (like searchting, removing, inserting...). – Lena Schimmel Dec 01 '11 at 12:43
  • Is there a TreeSet equivalent for `ArrayAdapter`? – JFreeman Mar 16 '18 at 06:58
  • Using TreeSet caused an ANR in my app. – Taslim Oseni Jul 19 '20 at 14:44
  • 1
    This doesn't answer the question because the default sort used for `String`s is lexicographic, not alphabetical. `'Z'` comes before `'a'`, unlike an alphabetical sort. – Chai T. Rex Nov 29 '20 at 14:45
38

You can create a new sorted copy using Java 8 Stream or Guava:

// Java 8 version
List<String> sortedNames = names.stream().sorted().collect(Collectors.toList());
// Guava version
List<String> sortedNames = Ordering.natural().sortedCopy(names); 

Another option is to sort in-place via Collections API:

Collections.sort(names);
Vitalii Fedorenko
  • 110,878
  • 29
  • 149
  • 111
  • 1
    The first example doesn't answer the question because the default sort used for `String`s is lexicographic, not alphabetical. `'Z'` comes before `'a'`, unlike an alphabetical sort. – Chai T. Rex Nov 29 '20 at 14:45
28

Better late than never! Here is how we can do it(for learning purpose only)-

import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

class SoftDrink {
    String name;
    String color;
    int volume; 

    SoftDrink (String name, String color, int volume) {
        this.name = name;
        this.color = color;
        this.volume = volume;
    }
}

public class ListItemComparision {
    public static void main (String...arg) {
        List<SoftDrink> softDrinkList = new ArrayList<SoftDrink>() ;
        softDrinkList .add(new SoftDrink("Faygo", "ColorOne", 4));
        softDrinkList .add(new SoftDrink("Fanta",  "ColorTwo", 3));
        softDrinkList .add(new SoftDrink("Frooti", "ColorThree", 2));       
        softDrinkList .add(new SoftDrink("Freshie", "ColorFour", 1));

        Collections.sort(softDrinkList, new Comparator() {
            @Override
            public int compare(Object softDrinkOne, Object softDrinkTwo) {
                //use instanceof to verify the references are indeed of the type in question
                return ((SoftDrink)softDrinkOne).name
                        .compareTo(((SoftDrink)softDrinkTwo).name);
            }
        }); 
        for (SoftDrink sd : softDrinkList) {
            System.out.println(sd.name + " - " + sd.color + " - " + sd.volume);
        }
        Collections.sort(softDrinkList, new Comparator() {
            @Override
            public int compare(Object softDrinkOne, Object softDrinkTwo) {
                //comparision for primitive int uses compareTo of the wrapper Integer
                return(new Integer(((SoftDrink)softDrinkOne).volume))
                        .compareTo(((SoftDrink)softDrinkTwo).volume);
            }
        });

        for (SoftDrink sd : softDrinkList) {
            System.out.println(sd.volume + " - " + sd.color + " - " + sd.name);
        }   
    }
}
Tirath
  • 2,294
  • 18
  • 27
  • 5
    Again, no justification for all this code when one line will do. See Lena's answer. – james.garriss Apr 10 '15 at 18:51
  • 1
    this might work as an exercise, but if i ever saw that in production code, i would axe it. immediately. – katzenhut Jul 28 '15 at 08:27
  • 2
    @james.garriss, Lena's answer was for simple list of string, this is for list of object which contains string attribute to be sorted. – Muneeb Mirza Oct 30 '18 at 12:41
  • 1
    Yeah this answer is extremly helpful when working in production with objects. List of Strings aren't that common. – JustRandom Apr 24 '20 at 15:52
  • This doesn't answer the question because the default sort used for `String`s is lexicographic, not alphabetical. `'Z'` comes before `'a'`, unlike an alphabetical sort. – Chai T. Rex Nov 29 '20 at 14:47
21

In one line, using Java 8:

list.sort(Comparator.naturalOrder());
Jonathan
  • 20,053
  • 6
  • 63
  • 70
Victor Petit
  • 2,632
  • 19
  • 19
  • 1
    This doesn't answer the question because the natural order `Comparator` used with `String`s is not alphabetical. `'Z'` comes before `'a'`, unlike an alphabetical sort. – Chai T. Rex Nov 29 '20 at 14:53
15

Unless you are sorting strings in an accent-free English only, you probably want to use a Collator. It will correctly sort diacritical marks, can ignore case and other language-specific stuff:

Collections.sort(countries, Collator.getInstance(new Locale(languageCode)));

You can set the collator strength, see the javadoc.

Here is an example for Slovak where Š should go after S, but in UTF Š is somewhere after Z:

List<String> countries = Arrays.asList("Slovensko", "Švédsko", "Turecko");

Collections.sort(countries);
System.out.println(countries); // outputs [Slovensko, Turecko, Švédsko]

Collections.sort(countries, Collator.getInstance(new Locale("sk")));
System.out.println(countries); // outputs [Slovensko, Švédsko, Turecko]
Oliv
  • 10,221
  • 3
  • 55
  • 76
11

Use the two argument for of Collections.sort. You will want a suitable Comparator that treats case appropriate (i.e. does lexical, not UTF16 ordering), such as that obtainable through java.text.Collator.getInstance.

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
10

Here is what you are looking for

listOfCountryNames.sort(String::compareToIgnoreCase)
Bijan
  • 7,737
  • 18
  • 89
  • 149
prashant
  • 348
  • 3
  • 13
7

more simply you can use method reference.

 list.sort(String::compareTo);
Roon
  • 81
  • 1
  • 3
5

By using Collections.sort(), we can sort a list.

public class EmployeeList {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        List<String> empNames= new ArrayList<String>();

        empNames.add("sudheer");
        empNames.add("kumar");
        empNames.add("surendra");
        empNames.add("kb");

        if(!empNames.isEmpty()){

            for(String emp:empNames){

                System.out.println(emp);
            }

            Collections.sort(empNames);

            System.out.println(empNames);
        }
    }
}

output:

sudheer
kumar
surendra
kb
[kb, kumar, sudheer, surendra]
Pritam Banerjee
  • 17,953
  • 10
  • 93
  • 108
ASR
  • 3,289
  • 3
  • 37
  • 65
  • 1
    This doesn't answer the question because the default sort used for `String`s is lexicographic, not alphabetical. `'Z'` comes before `'a'`, unlike an alphabetical sort. – Chai T. Rex Nov 29 '20 at 14:58
  • @Chai Collections.sort() sorts string in lexicographical order only. - 0...9 --> A-Z --> a-z – Shubham Arya Dec 22 '20 at 13:21
5

You can use the following line

Collections.sort(listOfCountryNames, String.CASE_INSENSITIVE_ORDER)

It is similar to the suggestion of Thilo, but will not make a difference between upper and lowercase characters.

Moritz Ringler
  • 9,772
  • 9
  • 21
  • 34
Ralf Hermann
  • 51
  • 1
  • 1
4

descending alphabet:

List<String> list;
...
Collections.sort(list);
Collections.reverse(list);
norbDEV
  • 4,795
  • 2
  • 37
  • 28
  • This is what I was looking for. Firstly I need to sort the list back to A-Z, and then Z-A for comparison. Good answer. – japes Sophey Nov 26 '19 at 15:55
1

Java 8 ,

countries.sort((country1, country2) -> country1.compareTo(country2));

If String's compareTo is not suitable for your need, you can provide any other comparator.

Sabir Khan
  • 9,826
  • 7
  • 45
  • 98
0

Same in JAVA 8 :-

//Assecnding order
listOfCountryNames.stream().sorted().forEach((x) -> System.out.println(x));

//Decending order
listOfCountryNames.stream().sorted((o1, o2) -> o2.compareTo(o1)).forEach((x) -> System.out.println(x));
Moritz Ringler
  • 9,772
  • 9
  • 21
  • 34
Vijay
  • 4,694
  • 1
  • 30
  • 38
  • 1
    This doesn't answer the question because the default sort used for `String`s is lexicographic, not alphabetical. `'Z'` comes before `'a'`, unlike an alphabetical sort. – Chai T. Rex Nov 29 '20 at 14:58
0
public static void sortByAlphabetCountry(List<Employee> listCountry) {
    listCountry.sort((o1, o2) -> {
        return o1.getName().compareTo(o2.getName());
    });
}
-1
//Here is sorted List alphabetically with syncronized
package com.mnas.technology.automation.utility;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

import org.apache.log4j.Logger;
/**
* 
* @author manoj.kumar
*/
public class SynchronizedArrayList {
static Logger log = Logger.getLogger(SynchronizedArrayList.class.getName());
@SuppressWarnings("unchecked")
public static void main(String[] args) {

List<Employee> synchronizedList = Collections.synchronizedList(new ArrayList<Employee>());
synchronizedList.add(new Employee("Aditya"));
synchronizedList.add(new Employee("Siddharth"));
synchronizedList.add(new Employee("Manoj"));
Collections.sort(synchronizedList, new Comparator() {
public int compare(Object synchronizedListOne, Object synchronizedListTwo) {
//use instanceof to verify the references are indeed of the type in question
return ((Employee)synchronizedListOne).name
.compareTo(((Employee)synchronizedListTwo).name);
}
}); 
/*for( Employee sd : synchronizedList) {
log.info("Sorted Synchronized Array List..."+sd.name);
}*/

// when iterating over a synchronized list, we need to synchronize access to the synchronized list
synchronized (synchronizedList) {
Iterator<Employee> iterator = synchronizedList.iterator();
while (iterator.hasNext()) {
log.info("Sorted Synchronized Array List Items: " + iterator.next().name);
}
}

}
}
class Employee {
String name;
Employee (String name) {
this.name = name;

}
}
  • But why? Why is it better to use these 50 lines of code than the 1 line of code in Lena's answer? – james.garriss Feb 27 '15 at 14:15
  • Because,The sort(List,Comparator super T>) method is used to sort the specified list according to the order induced by the specified comparator. When you want to sort a list of Emplpyee according to their names & ages then use the method Collections sort(List,Comparator) –  Mar 23 '15 at 07:31
  • Nope, sorry, not feeling any love here. You're answering a different question, namely how to sort a List of Objects by their properties. Your code might be useful for that purpose, but it's way overkill for the OP's question. :-( – james.garriss Apr 10 '15 at 18:49
  • This doesn't answer the question because the default sort used for `String`s is lexicographic, not alphabetical. `'Z'` comes before `'a'`, unlike an alphabetical sort. – Chai T. Rex Nov 29 '20 at 15:00