Sort a list with known values before unknown values

Barney :

I'm trying to sort a list with the following rules:

  1. Known values should be ordered before unknown values.
  2. Known values should be ordered by a separately defined key.
  3. Unknown values should be ordered by their natural ordering.

I've got (1) and (2), just struggling with adding (3) in to the mix.

So far I have this:

List<String> values = Arrays.asList(
    "red", "orange", "yellow", "green", "blue", "indigo", "violet");

ImmutableMap<String, Integer> map = ImmutableMap.of("red", 1, "green", 2, "blue", 3);

Ordering<String> order = Ordering.natural()
    .nullsLast()
    .onResultOf(Functions.forMap(map, null));

Collections.sort(values, order);

System.out.println(values);

Which produces:

[red, green, blue, orange, yellow, indigo, violet]

But the last 4 are in their original order, whereas I'd like them sorted in their natural order:

[red, green, blue, indigo, orange, violet, yellow]

The only thing I can think of is writing my own custom function, which looks things up in the map and prepends the map result to the original value, using the map size if not found - e.g. it would return:

"1-red", "4-orange", "4-yellow", "2-green", "3-blue", "4-indigo", "4-violet"

But that only works if the mapped values are integers, and requires number formatting to order "02" before "10" etc.

Anyone have a better way of achieving this?

Tomasz Linkowski :

Here's the Guava version (when you're on Java 7 or lower):

Ordering<String> ordering = Ordering.natural().nullsLast()
        .onResultOf(Functions.forMap(map, null))
        .compound(Ordering.natural());

Here's the non-Guava version using pure Comparator (when on JDK 8+):

Comparator<String> comparator = Comparator
        .<String, Integer>comparing(map::get, Comparator.nullsLast(Comparator.naturalOrder()))
        .thenComparing(Comparator.naturalOrder());

PS. As you can see, the type inference in case of the Guava API is better (no need to specify explicit type parameters).

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=94015&siteId=1