Java 在未知值之前使用已知值对列表进行排序
我尝试使用以下规则对列表进行排序:Java 在未知值之前使用已知值对列表进行排序,java,guava,java-7,comparator,Java,Guava,Java 7,Comparator,我尝试使用以下规则对列表进行排序: 已知值应在未知值之前排序 已知值应按单独定义的键排序 未知值应按其自然顺序排序 我有(1)和(2),只是在混音中加入(3)很困难 到目前为止,我有: List<String> values = Arrays.asList( "red", "orange", "yellow", "green", "blue", "indigo", "violet"); ImmutableMap<String, Integer> map = Im
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);
但最后4个是按原始顺序排列的,而我希望它们按自然顺序排列:
[red, green, blue, indigo, orange, violet, yellow]
我能想到的唯一一件事就是编写自己的自定义函数,该函数在地图中查找并将地图结果预先设置为原始值,如果未找到,则使用地图大小-例如,它将返回:
"1-red", "4-orange", "4-yellow", "2-green", "3-blue", "4-indigo", "4-violet"
但这仅适用于映射值为整数的情况,并且要求数字格式将“02”排在“10”之前,以此类推
有谁有更好的方法来实现这一点吗?这是番石榴的版本(当您使用Java 7或更低版本时):
如您所见,GuavaAPI的类型推断更好(无需指定显式类型参数)。我认为这个解决方案应该可以解决您的问题。很抱歉我使用了
ArrayList
s-我在Java8API中找不到任何与ImmutableMap
对应的文档。我还假设自然顺序意味着ASCII顺序。希望这有帮助:)
//要排序的值
ArrayList值=新的ArrayList();
添加(“红色”);
添加(“橙色”);
添加(“橙色”);
添加(“黄色”);
添加(“绿色”);
添加(“蓝色”);
添加(“靛蓝”);
添加(“紫色”);
增加(1)//我添加了1来验证输出
//包含已知值顺序的列表
ArrayList knownOrder=新的ArrayList();
knownOrder.添加(“红色”);
增加(1);
添加(“绿色”);
knownOrder.添加(“蓝色”);
增加(3);
ArrayList knownValues=新的ArrayList();
ArrayList unknownValues=新的ArrayList();
用于(对象值:值){
if(knownOrder.contains(value)){
增加(价值);
}否则{
未知值。添加(值);
}
}
//按所需顺序对已知值进行排序
Collections.sort(knownvalue,(m1,m2)->knownOrder.indexOf(m1)-knownOrder.indexOf(m2));
//按自然顺序对未知值排序
Collections.sort(未知值,(m1,m2)->m1.toString().charAt(0)-m2.toString().charAt(0));
//将已知值和未知值合并到一个ArrayList中
已知值。addAll(未知值);
System.out.println(已知值);
//印刷品[红色、1、绿色、蓝色、靛蓝、橙色、橙色、紫色、黄色]
我还应该提到:此解决方案不适用于字符串和基本包装之外的对象。我建议您将示例值更改为“红色”、“绿色”和“蓝色”未排序的顺序(例如,
“红色”、“橙色”、“黄色”、“蓝色”、“绿色”、“靛蓝”、“紫色”
)。否则,很难验证解决方案是否满足条件2.或Comparator.comparingInt((字符串s)->map.getOrDefault(s,Integer.MAX_值))。然后进行比较(Comparator.naturalOrder())
,假设Integer.MAX_值
从未作为映射值出现。
"1-red", "4-orange", "4-yellow", "2-green", "3-blue", "4-indigo", "4-violet"
Ordering<String> ordering = Ordering.natural().nullsLast()
.onResultOf(Functions.forMap(map, null))
.compound(Ordering.natural());
Comparator<String> comparator = Comparator
.<String, Integer>comparing(map::get, Comparator.nullsLast(Comparator.naturalOrder()))
.thenComparing(Comparator.naturalOrder());
//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]