提问人:Satish Jajimoggala 提问时间:5/20/2022 最后编辑:Alexander IvanchenkoSatish Jajimoggala 更新时间:5/20/2022 访问量:719
如何对字符串的嵌套列表进行排序
How to Sort a Nested List of strings
问:
我想按列表中的值对列表进行排序。我想根据列表中的几个参数进行多重排序。提供数据外观的示例示例。
注意:我无法将 List<List<String>>
转换为对象列表。
List<List<String>> data = new ArrayList<>();
List<String> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();
List<String> list3 = new ArrayList<>();
list1.add("Siva");
list1.add("20");
list1.add("Hyd");
list1.add("TA");
list1.add("India");
list2.add("Suresh");
list2.add("22");
list2.add("Banglore");
list2.add("KA");
list2.add("India");
list3.add("Ramesh");
list3.add("24");
list3.add("Chennai");
list3.add("TN");
list3.add("India");
data.add(list1);
data.add(list2);
data.add(list2);
我想根据 和 做多排序。name
age
city
这只是示例数据。列表列表是动态的。排序参数有时也会更改。
我只想对字符串列表列表进行排序。
预期输出:List<List<String>> sortedData
答:
0赞
dani-vta
5/20/2022
#1
通过维护结构来解决问题
如果无法真正创建一个将数据包装在嵌套中的类(无论出于何种原因),则可以使用集合流并定义操作的逻辑,如下所示:List
sorted
List<List<String>> listRes = data.stream()
.sorted((x, y) -> {
int res = x.get(0).compareTo(y.get(0)); //Comparing by name
if (res != 0) return res;
res = Integer.valueOf(x.get(1)).compareTo(Integer.valueOf(y.get(1))); //Comparing by age (numeric value)
if (res != 0) return res;
return x.get(2).compareTo(y.get(2)); //Comapring by city
})
.collect(Collectors.toList());
用于测试上述代码的链接:
替代解决方案
但是,正如注释中指出的那样,更好的方法是创建一个自定义类,以表示嵌套 .如果您将 Java 14 或更高版本与工厂方法结合使用,则可能是一个简单的记录,以便从嵌套的 .List
List
然后,使用流,您可以将每个嵌套列表映射到自定义类,并使用 .Comparator
下面是实现的片段:
public static void main(String[] args) {
List<List<String>> data = /* ... your initialization ... */
List<MyClass> listSorted = data.stream()
.map(list -> MyClass.createMyClass(list))
.sorted(Comparator.comparing(MyClass::getName).thenComparing(MyClass::getAge).thenComparing(MyClass::getCity))
.collect(Collectors.toList());
System.out.println(listSorted);
}
映射记录
record MyClass(String name, int age, String city, String code, String country) {
public static MyClass createMyClass(List<String> list) {
if (list == null || list.size() < 5) {
return null;
}
MyClass mc = new MyClass();
mc.name = list.get(0);
mc.age = Integer.valueOf(list.get(1));
mc.city = list.get(2);
mc.code = list.get(3);
mc.country = list.get(4);
return mc;
}
}
这里还有一个与两个实现的链接:
评论
0赞
Satish Jajimoggala
5/20/2022
在我的情况下,创建自定义类将不起作用
0赞
dani-vta
5/20/2022
@SatishJajimoggala看看第一个解决方案和我发布的链接。还有一个解决方案是按照需要维护嵌套列表
0赞
Alexander Ivanchenko
5/20/2022
#2
为了在嵌套列表中强加列表的顺序,需要定义一个比较器
。
正如您所说,无法提前预测列表的内容,我假设嵌套列表可能具有任意大小,并且它们的大小可能不相等。
可以处理这种情况的比较器可以这样写:
Comparator<List<String>> listComparator = new Comparator<>() {
@Override
public int compare(List<String> o1, List<String> o2) {
int limit = Math.min(o1.size(), o2.size());
for (int i = 0; i < limit; i++) {
int localResult = o1.get(i).compareTo(o2.get(i));
if (localResult != 0)
return localResult;
}
return o1.size() - o2.size();
}
};
为了对列表进行排序,您可以在其上应用方法(Java 8+ 可用),该方法需要比较器:sort()
data.sort(listComparator);
您可以在申请之前制作列表的防御性副本,如果它的初始顺序可能对您有用:sort()
List<List<String>> initialOrder = new ArrayList<>(data);
data.sort(listComparator);
评论
I don't have feasibility to convert data in to list of object
->是的,你有。此外,您还需要定义预期的输出。其他方面,没有目标。最后,你需要付出一些努力。String
List
name,age,city
"100"
"20"