0

I have created the following method:

public List<String> listAll() {
    List worldCountriesByLocal = new ArrayList();

    for (Locale locale : Locale.getAvailableLocales()) {
        final String isoCountry = locale.getDisplayCountry();
        if (isoCountry.length() > 0) {
            worldCountriesByLocal.add(isoCountry);
            Collections.sort(worldCountriesByLocal);
        }
    }
    return worldCountriesByLocal;
}

Its pretty simple and it returns a list of world countries in the users locale. I then sort it to get it alphabetic. This all works perfectly (except I seem to occasionally get duplicates of countries!).

Anyway, what I need is to place the US, and UK at the top of the list regardless. The problem I have is that I can't isolate the index or the string that will be returned for the US and UK because that is specific to the locale!

Any ideas would be really appreciated.

tarka
  • 5,289
  • 10
  • 51
  • 75

4 Answers4

8

Anyway, what I need is to place the US, and UK at the top of the list regardless. The problem I have is that I can't isolate the index or the string that will be returned for the US and UK because that is specific to the locale!

It sounds like you should implement your own Comparator<Locale> to compare two locales with the following steps:

  • If the locales are the same, return 0
  • If one locale is the US, make that "win"
  • If one locale is the UK, make that "win"
  • Otherwise, use o1.getDisplayCountry().compareTo(o2.getDisplayCountry()) (i.e. delegate to existing behaviour)

(This will put the US before the UK.)

Then call Collections.sort with an instance of your custom comparator.

Do all of this before extracting the country names - then extract them from the sorted list.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
1

yes, when you do sort, just provide your own comparator

Collections.sort(worldCountriesByLocal, new Comparator() {

    @Override
    public int compare(String o1, String o2) {
        if (o1.equals(TOP_VALUE))
            return -1;
        if (o2.equals(TOP_VALUE))
            return 1;
        return o1.compareTo(o2);
    }
})

where top value will be value what you want to always on top

user902383
  • 8,420
  • 8
  • 43
  • 63
1

I would write my own POJO with a sort token consisting of an integer assigning priority (e.g. 0 for US, 1 for UK, 2 for everyone else), then some delimiter and then the country name. Then I would put the array in a HashMap keyed by that sort ID and the POJO as the val. Then I would sort the keys out of the map and iterate through the sorting and retrieve the plain country name for each sorted key.

E.g.

2.Sweden
2.France
2.Tanzania
0.US
1.UK

sorts

0.US
1.UK
2.France
2.Sweden
2.Tanzania

EDIT: a POJO is needed only if you have more fields other than the country name. If it is just the country name, I would set the sort ID as the hash key and the country name as the val and skip the POJO part.

amphibient
  • 29,770
  • 54
  • 146
  • 240
1

You could also use a TreeSet to eliminate duplicates and your own Comparator to bring US and GB up to the start.

You are getting duplicates (which this will eliminate) because there are often more than one locale per country. There is a US(Spanish) as well as a US(English) and there are three Switzerlands (French, German and Italian) for example.

public class AllLocales {
  // Which Locales get priority.
  private static final Locale[] priorityLocales = {
    Locale.US,
    Locale.UK
  };

  private static class MyLocale implements Comparable<MyLocale> {
    // My Locale.
    private final Locale me;

    public MyLocale(Locale me) {
      this.me = me;
    }

    // Convenience
    public String getCountry() {
      return me.getCountry();
    }

    @Override
    public int compareTo(MyLocale it) {
      // No duplicates in the country field.
      if (getCountry().equals(it.getCountry())) {
        return 0;
      }
      // Check for priority ones.
      for (int i = 0; i < priorityLocales.length; i++) {
        Locale priority = priorityLocales[i];
        // I am a priority one.
        if (getCountry().equals(priority.getCountry())) {
          // I come first.
          return -1;
        }
        // It is a priority one.
        if (it.getCountry().equals(priority.getCountry())) {
          // It comes first.
          return 1;
        }
      }
      // Default to straight comparison.
      return getCountry().compareTo(it.getCountry());
    }
  }

  public static List<String> listAll() {
    Set<MyLocale> byLocale = new TreeSet();
    // Gather them all up.
    for (Locale locale : Locale.getAvailableLocales()) {
      final String isoCountry = locale.getDisplayCountry();
      if (isoCountry.length() > 0) {
        //System.out.println(locale.getCountry() + ":" + isoCountry + ":" + locale.getDisplayName());
        byLocale.add(new MyLocale(locale));
      }
    }
    // Roll them out of the set.
    ArrayList<String> list = new ArrayList<>();
    for (MyLocale l : byLocale) {
      list.add(l.getCountry());
    }
    return list;
  }

  public static void main(String[] args) throws InterruptedException {
    // Some demo usages.
    List<String> locales = listAll();
    System.out.println(locales);
  }
}
OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213