如何根据用户从下拉菜单中选择的参数对 Java 个对象列表进行排序?
How can I sort a list of Java objects based on parameters that a user selects from a drop down menu?
我了解如何根据对象的多个属性构建和使用 Comparator
对象列表。但是,我不确定如何通过让用户选择要排序的参数来有效地做到这一点。这是一个GWT
UI。
比如我有两个下拉菜单,每个有11个参数,对应对象的属性。每个菜单也作为旁边的一个按钮来指定ascending/descending顺序。
因此,用户可以选择按 fileName, desc
和 timestamp, asc
排序。我怎样才能对这些对象进行排序,而不用长得离谱的 if
语句来表示几百种可能的组合?
如果排序是固定的,我可以这样做:
files.sort(Comparator.comparing(FileInfo::getFileName).thenComparing(FileInfo::getTimestamp).reversed());
(我可能把 asc/desc 倒过来了)
但我不应该为每个可能的选项都输入它。那我该怎么做呢?
您可以尝试创建一个枚举:
public enum FileInfoComparator {
FILE_NAME(Comparator.comparing(FileInfo::getFileName)),
TIMESTAMP(Comparator.comparing(FileInfo::getTimestamp)),
SIZE(Comparator.comparing(FileInfo::getSize)),
// ... add other criteria here
;
private final Comparator<FileInfo> comparator;
FileInfoComparator(Comparator<FileInfo> comparator) {
this.comparator = comparator;
}
static Comparator<FileInfo> by(String key, boolean ascending) {
Comparator<FileInfo> comparator = valueOf(key).comparator;
return ascending ? comparator : comparator.reversed();
}
static Comparator<FileInfo> by(Pair<String, Boolean> criterion) {
return by(criterion.getKey(), criterion.getValue());
}
static Optional<Comparator<FileInfo>> by(List<Pair<String, Boolean>> criteria) {
return criteria.stream()
.map(FileInfoComparator::by)
.filter(Objects::nonNull)
.reduce(Comparator::thenComparing);
}
}
然后使用:
// Create the list of selected criteria based on user input:
// E.g. [FILE_NAME, false] will mean "sort by fileName descending"
List<Pair<String, Boolean>> selectedCriteria = ...
// Build your comparator and sort your list
FileInfoComparator.by(selectedCriteria).ifPresent(files::sort);
如果用户选择为空,files
将保持不变。
我了解如何根据对象的多个属性构建和使用 Comparator
对象列表。但是,我不确定如何通过让用户选择要排序的参数来有效地做到这一点。这是一个GWT
UI。
比如我有两个下拉菜单,每个有11个参数,对应对象的属性。每个菜单也作为旁边的一个按钮来指定ascending/descending顺序。
因此,用户可以选择按 fileName, desc
和 timestamp, asc
排序。我怎样才能对这些对象进行排序,而不用长得离谱的 if
语句来表示几百种可能的组合?
如果排序是固定的,我可以这样做:
files.sort(Comparator.comparing(FileInfo::getFileName).thenComparing(FileInfo::getTimestamp).reversed());
(我可能把 asc/desc 倒过来了)
但我不应该为每个可能的选项都输入它。那我该怎么做呢?
您可以尝试创建一个枚举:
public enum FileInfoComparator {
FILE_NAME(Comparator.comparing(FileInfo::getFileName)),
TIMESTAMP(Comparator.comparing(FileInfo::getTimestamp)),
SIZE(Comparator.comparing(FileInfo::getSize)),
// ... add other criteria here
;
private final Comparator<FileInfo> comparator;
FileInfoComparator(Comparator<FileInfo> comparator) {
this.comparator = comparator;
}
static Comparator<FileInfo> by(String key, boolean ascending) {
Comparator<FileInfo> comparator = valueOf(key).comparator;
return ascending ? comparator : comparator.reversed();
}
static Comparator<FileInfo> by(Pair<String, Boolean> criterion) {
return by(criterion.getKey(), criterion.getValue());
}
static Optional<Comparator<FileInfo>> by(List<Pair<String, Boolean>> criteria) {
return criteria.stream()
.map(FileInfoComparator::by)
.filter(Objects::nonNull)
.reduce(Comparator::thenComparing);
}
}
然后使用:
// Create the list of selected criteria based on user input:
// E.g. [FILE_NAME, false] will mean "sort by fileName descending"
List<Pair<String, Boolean>> selectedCriteria = ...
// Build your comparator and sort your list
FileInfoComparator.by(selectedCriteria).ifPresent(files::sort);
如果用户选择为空,files
将保持不变。