我有一个包含多个变量的对象列表。我想根据运行时决定的顺序对这个列表进行排序。我想出了以下看起来效率不高的代码。例如,如果变量不是 3 而是 10 或 30 会怎样?谁能建议更好的方法来做到这一点?
import java.util.List;
import java.util.function.Function;
import static java.util.Comparator.*;
import static java.util.stream.Collectors.*;
public class SortXYZ {
double x;
String y;
double z;
public double getX() {return x; }
public String getY() {return y; }
public double getZ() {return z; }
public static void main(String[] arg) {
Function<SortXYZ, Double> f1 = SortXYZ::getX;
Function<SortXYZ, String> f2 = SortXYZ::getY;
Function<SortXYZ, Double> f3 = SortXYZ::getZ;
//could have f4, f5 etc.
List<SortXYZ> list = getList(); //get a list of SortXYZ objects
String sortSeq = arg[0];
if (sortSeq.equals("XYZ")) {
list = list.stream().sorted(comparing(f1).thenComparing(f2).thenComparing(f3)).collect(toList());
} else if (sortSeq.equals("XZY")) {
list = list.stream().sorted(comparing(f1).thenComparing(f3).thenComparing(f2)).collect(toList());
} else if (sortSeq.equals("YXZ")) {
list = list.stream().sorted(comparing(f2).thenComparing(f1).thenComparing(f3)).collect(toList());
} else if (sortSeq.equals("YZX")) {
list = list.stream().sorted(comparing(f2).thenComparing(f3).thenComparing(f1)).collect(toList());
} else if (sortSeq.equals("ZXY")) {
list = list.stream().sorted(comparing(f3).thenComparing(f1).thenComparing(f2)).collect(toList());
} else if (sortSeq.equals("ZYX")) {
list = list.stream().sorted(comparing(f3).thenComparing(f2).thenComparing(f1)).collect(toList());
}
}
}
最佳答案
我暂时忽略了 Comparator
中的原始类型。稍后将尝试提高类型安全性。
您可以创建接受比较器模式的方法,并基于它创建一个比较器。为了让生活更轻松,您还可以将 getter 引用(f1
f2
..)存储在 map 中,例如
@SuppressWarnings("rawtypes")
static Map<String, Function<SortXYZ, Comparable>> gettersMap = new HashMap<>();
static {
gettersMap.put("x", SortXYZ::getX);
gettersMap.put("y", SortXYZ::getY);
gettersMap.put("z", SortXYZ::getZ);
}
所以创建比较器的方法看起来像
@SuppressWarnings("unchecked")
static Comparator<SortXYZ> getComparator(String order){
String[] keys = order.toLowerCase().split("");
Comparator<SortXYZ> result = Comparator.comparing(gettersMap.get(keys[0]));
for (int i = 1; i<keys.length; i++){
result = result.thenComparing(gettersMap.get(keys[i]));
}
return result;
}
顺便说一句:在你的代码中:
list = list.stream().sorted(Comparator.comparing(f3).thenComparing(f2).thenComparing(f1)).collect(toList());
您正在对列表进行排序,并将元素写入新列表,然后再次将其分配给 list
引用。如果你想对当前列表中的元素进行排序,你可以简单地使用
list.sort(yourComparator);
因此您的代码现在看起来更像:
List<SortXYZ> list = getList(); //get a list of SortXYZ objects
String sortSeq = arg[0];
list.sort(getComparator(sortSeq));
关于java - 使用 Java 8 流对多个变量列表进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30624612/