我正在尝试使用以下规则对列表进行排序:
我有(1)和(2),只是想在混合中添加(3)。
到目前为止,我有这个:
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);
哪个会产生:
[red, green, blue, orange, yellow, indigo, violet]
但是最后4个按其原始顺序排列,而我希望它们按其自然顺序排序:
[red, green, blue, indigo, orange, violet, yellow]
我唯一想到的就是编写自己的自定义函数,该函数会在地图中查找内容并将地图结果添加到原始值,如果找不到地图,则使用地图大小-例如它会返回:
"1-red", "4-orange", "4-yellow", "2-green", "3-blue", "4-indigo", "4-violet"
但这仅在映射值是整数且要求数字格式将“ 02”放在“ 10”之前的情况下有效。
有人有更好的方法实现这一目标吗?
答案 0 :(得分:4)
这是Guava版本(当您使用Java 7或更低版本时):
Ordering<String> ordering = Ordering.natural().nullsLast()
.onResultOf(Functions.forMap(map, null))
.compound(Ordering.natural());
这是使用纯Comparator
的非番石榴版本(在JDK 8+上):
Comparator<String> comparator = Comparator
.<String, Integer>comparing(map::get, Comparator.nullsLast(Comparator.naturalOrder()))
.thenComparing(Comparator.naturalOrder());
PS。如您所见,使用Guava API的类型推断更好(不需要指定显式类型参数)。
答案 1 :(得分:0)
我认为该解决方案应该可以解决您的问题。我为使用ArrayList
而致歉-我在Java 8 API中找不到与ImmutableMap
相对应的任何文档。我还假定 natural 顺序表示ASCII顺序。希望这会有所帮助:)
//Values to be sorted
ArrayList<Object> values = new ArrayList<>();
values.add("red");
values.add("orange");
values.add("orange");
values.add("yellow");
values.add("green");
values.add("blue");
values.add("indigo");
values.add("violet");
values.add(1); //I added 1 to verify output
//List containing order of known values
ArrayList<Object> knownOrder = new ArrayList<>();
knownOrder.add("red");
knownOrder.add(1);
knownOrder.add("green");
knownOrder.add("blue");
knownOrder.add(3);
ArrayList<Object> knownValues = new ArrayList<>();
ArrayList<Object> unknownValues = new ArrayList<>();
for (Object value: values) {
if (knownOrder.contains(value)) {
knownValues.add(value);
}else {
unknownValues.add(value);
}
}
//Sort known values in required order
Collections.sort(knownValues, (m1, m2)->knownOrder.indexOf(m1)-knownOrder.indexOf(m2));
//Sort unknown values in natural order
Collections.sort(unknownValues, (m1, m2)->m1.toString().charAt(0)-m2.toString().charAt(0));
//Combine the known and unknown values into one ArrayList
knownValues.addAll(unknownValues);
System.out.println(knownValues);
//Prints [red, 1, green, blue, indigo, orange, orange, violet, yellow]
我还应该提到:该解决方案不适用于String和原始Wrappers以外的对象。