如何对地图列表进行二次排序
How can I do a secondary sorting on a list of maps
假设我有以下地图列表
[{id:1,count:2,name:xyz},
{id:2,count:3,name:def},
{id:3,count:2,name:abc},
{id:4,count:5,name:ghj}
]
我想先按计数再按名称对这张地图进行排序:
期望的输出:
[{id:3,count:2,name:abc},
{id:1,count:2,name:xyz},
{id:2,count:3,name:def},
{id:4,count:5,name:ghj}
]
我尝试了以下进行第一次排序,但在按计数排序后无法使用名称排序
Collections.sort(list, new Comparator() {
public int compare(Object o1, Object o2) {
return ((Comparable) ((Map.Entry) (o1)).getValue())
.compareTo(((Map.Entry) (o2)).getValue());
}
假设list
的类型是List<Map<String,Object>>
(不清楚Map
的值是什么类型,所以我用了Object
),你的Comparator
应该能够比较两个 Map<String,Object>
个实例。
Collections.sort(list, new Comparator<Map<String,Object>>() {
public int compare(Map<String,Object> o1, Map<String,Object> o2) {
// first compare o1.get("count") to o2.get("count")
// if they are equal, compare o1.get("name") to o2.get("name")
// don't forget to handle nulls (for example if either o1 or o2 is null
// or if any of the keys are not present in one or both of the maps)
}
如果我没理解错的话,你有一个List<Map<String, Object>>
。您需要编写自定义 Comparator
才能对其进行排序。在那里,您可以分别比较每个条目(为勇敢起见删除了错误处理):
public class ListMapComparator implements Comparator<List<Map<String, Object>>> {
@Override
public in compare (List<Map<String, Object>> l1, List<Map<String, Object>> l2) {
Integer count1 = (Integer)l1.get("count");
Integer count2 = (Integer)l2.get("count");
int comp = count1.compare(count2);
if (comp != 0) {
return comp;
}
String name1 = (String)l1.get("name");
String name2 = (String)l2.get("name");
return name1.compare(name2);
}
}
在 Java 1.8 中,我将使用新的 Comparator 方法(尽管缺少类型推断使得有必要声明所有类型,从而降低易感性):
final Comparator<Map<String, Comparable<Object>>> nameThenCountComparator = Comparator.<Map<String, Comparable<Object>>, Comparable<Object>> comparing(
m -> m.get("name")).thenComparing(Comparator.<Map<String, Comparable<Object>>, Comparable<Object>> comparing(
m -> m.get("count")));
对于 Java 1.7,我可能会使用 chainedComparator(请参阅 Apache 的 ComparatorUtils or Guava's Ordering)和自定义 MapValueComparator(公共库中可能有一个,但尚未找到)。然后想要的顺序变得非常可读:
class MapValueComparator implements Comparator<Map<String, Object>> {
private final String key;
public MapValueComparator(final String key) {
this.key = key;
}
@Override
public int compare(final Map<String, Object> o1, final Map<String, Object> o2) {
return ((Comparable<Object>)o1.get(key)).compareTo(o2.get(key));
}
}
Comparator<Object> nameThenCountComparator = ComparatorUtils.chainedComparator(
new MapValueComparator("name"),
new MapValueComparator("count")
);
然后使用它(Java 7 或 8):
final List<Map<String, Comparable<Object>>> list = null;
Collections.sort(list, nameThenCountComparator);
Rq:如其他答案所述,您应该检查 MapValueComparator 中的空值和缺失键。
假设我有以下地图列表
[{id:1,count:2,name:xyz},
{id:2,count:3,name:def},
{id:3,count:2,name:abc},
{id:4,count:5,name:ghj}
]
我想先按计数再按名称对这张地图进行排序:
期望的输出:
[{id:3,count:2,name:abc},
{id:1,count:2,name:xyz},
{id:2,count:3,name:def},
{id:4,count:5,name:ghj}
]
我尝试了以下进行第一次排序,但在按计数排序后无法使用名称排序
Collections.sort(list, new Comparator() {
public int compare(Object o1, Object o2) {
return ((Comparable) ((Map.Entry) (o1)).getValue())
.compareTo(((Map.Entry) (o2)).getValue());
}
假设list
的类型是List<Map<String,Object>>
(不清楚Map
的值是什么类型,所以我用了Object
),你的Comparator
应该能够比较两个 Map<String,Object>
个实例。
Collections.sort(list, new Comparator<Map<String,Object>>() {
public int compare(Map<String,Object> o1, Map<String,Object> o2) {
// first compare o1.get("count") to o2.get("count")
// if they are equal, compare o1.get("name") to o2.get("name")
// don't forget to handle nulls (for example if either o1 or o2 is null
// or if any of the keys are not present in one or both of the maps)
}
如果我没理解错的话,你有一个List<Map<String, Object>>
。您需要编写自定义 Comparator
才能对其进行排序。在那里,您可以分别比较每个条目(为勇敢起见删除了错误处理):
public class ListMapComparator implements Comparator<List<Map<String, Object>>> {
@Override
public in compare (List<Map<String, Object>> l1, List<Map<String, Object>> l2) {
Integer count1 = (Integer)l1.get("count");
Integer count2 = (Integer)l2.get("count");
int comp = count1.compare(count2);
if (comp != 0) {
return comp;
}
String name1 = (String)l1.get("name");
String name2 = (String)l2.get("name");
return name1.compare(name2);
}
}
在 Java 1.8 中,我将使用新的 Comparator 方法(尽管缺少类型推断使得有必要声明所有类型,从而降低易感性):
final Comparator<Map<String, Comparable<Object>>> nameThenCountComparator = Comparator.<Map<String, Comparable<Object>>, Comparable<Object>> comparing(
m -> m.get("name")).thenComparing(Comparator.<Map<String, Comparable<Object>>, Comparable<Object>> comparing(
m -> m.get("count")));
对于 Java 1.7,我可能会使用 chainedComparator(请参阅 Apache 的 ComparatorUtils or Guava's Ordering)和自定义 MapValueComparator(公共库中可能有一个,但尚未找到)。然后想要的顺序变得非常可读:
class MapValueComparator implements Comparator<Map<String, Object>> {
private final String key;
public MapValueComparator(final String key) {
this.key = key;
}
@Override
public int compare(final Map<String, Object> o1, final Map<String, Object> o2) {
return ((Comparable<Object>)o1.get(key)).compareTo(o2.get(key));
}
}
Comparator<Object> nameThenCountComparator = ComparatorUtils.chainedComparator(
new MapValueComparator("name"),
new MapValueComparator("count")
);
然后使用它(Java 7 或 8):
final List<Map<String, Comparable<Object>>> list = null;
Collections.sort(list, nameThenCountComparator);
Rq:如其他答案所述,您应该检查 MapValueComparator 中的空值和缺失键。