在有空单元格的情况下对列进行排序时遇到问题。
我为Comparator
列创建了一个新的codeMed
:
codeMed.setComparator(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
if (o1 == null)return -1;
if (o2 == null) return -1;
return o1 < o2 ? -1 : o1 == o2 ? 0 :1;
}
});
起初,它似乎工作正常:
但是,如果我决定对其他列进行排序,然后对codeMed列进行排序,则会发生这种情况:
我认为错误出在比较器中,但我不知道出了什么问题。
编辑:我希望空值始终位于该列的底部。我尝试过这样的事情:
if (codeMed.getSortType() == TableColumn.SortType.DESCENDING) {
return (o1 != null ? o1 : Integer.MAX_VALUE) - (o2 != null ? o2 : Integer.MAX_VALUE);
} else if (codeMed.getSortType()==TableColumn.SortType.ASCENDING){
return (o1 != null ? o1 : Integer.MIN_VALUE) - (o2 != null ? o2 : Integer.MIN_VALUE);
}
return 0;
但是它不起作用:/(也许是因为Slaw建议的问题)
我的解决方案:
非常感谢Jai,我修改了代码,只是因为我想将其用于2个不同的列:
Comparator<Integer> integerComparator = new Comparator<>() {
@Override
public int compare(Integer o1, Integer o2) {
final boolean isDesc = tabInfosPatient.getSortOrder().get(0).getSortType() == TableColumn.SortType.DESCENDING;
if (o1 == null && o2 == null) return 0;
else if (o1 == null) return isDesc ? -1 : 1;
else if (o2 == null) return isDesc ? 1 : -1;
else return Integer.compare(o1, o2);
}
};
答案 0 :(得分:2)
令我惊讶的是,它甚至曾经工作过一次。我认为这会很好:
codeMed.setComparator(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return (o1 != null ? o1 : Integer.MAX_VALUE) - (o2 != null ? o2 : Integer.MAX_VALUE);
}
});
这将假定任何null
值都被视为代表最大的int
值。这将迫使它移动到列表底部的升序排序列中,如果它在降序的排序列中则移到顶部。如果需要反向操作,请将Integer.MAX_VALUE
切换到Integer.MIN_VALUE
。
您所做的操作无效,因为您违反了以下规定:
实施者必须确保sgn(compare(x,y))== -sgn(compare(y, x))表示所有x和y。(这意味着compare(x,y)必须抛出一个 并且仅当compare(y,x)引发异常时才发生异常。)
当o1
为5
而o2
为null
时,便是这种违规的例子。在这种情况下,compare(o1, o2)
返回-1
,而compare(o2, o1)
也返回-1
。其中一个应返回正值,而另一个应返回负值,或者都必须返回0
。
这就是您所需要的。
public class Model {
private final ObjectProperty<Integer> v = new SimpleObjectProperty<>();
public Model(Integer v) {
this.v.setValue(v);
}
public final ObjectProperty<Integer> vProperty() {
return this.v;
}
public final Integer getV() {
return this.vProperty().get();
}
public final void setV(final Integer v) {
this.vProperty().set(v);
}
}
ObservableList<Model> list = FXCollections.observableArrayList();
list.addAll(new Model(20), new Model(-30), new Model(null), new Model(10));
TableView<Model> tv = new TableView<>();
TableColumn<Model, Integer> tc = new TableColumn<>();
tc.setCellValueFactory(new PropertyValueFactory<>("v"));
tv.getColumns().add(tc);
tv.setItems(list);
Comparator<Integer> ascComparator = (o1, o2) ->
(o1 != null ? o1 : Integer.MAX_VALUE) -
(o2 != null ? o2 : Integer.MAX_VALUE);
Comparator<Integer> descComparator = (o1, o2) ->
(o1 != null ? o1 : Integer.MIN_VALUE) -
(o2 != null ? o2 : Integer.MIN_VALUE);
@SuppressWarnings("unchecked")
Comparator<Integer> defaultComparator = TableColumn.DEFAULT_COMPARATOR;
tc.comparatorProperty().bind(
Bindings.when(tc.sortTypeProperty().isEqualTo(SortType.ASCENDING))
.then(ascComparator)
.otherwise(
Bindings.when(tc.sortTypeProperty().isEqualTo(SortType.DESCENDING))
.then(descComparator)
.otherwise(defaultComparator)));
此外,我想指出的是,尽管在大多数情况下使用Integer.MIN_VALUE
和Integer.MAX_VALUE
都可以工作,但整数下溢和溢出问题的风险要高得多,我不是确定使用比较器和可比较器是否存在问题。
如果您想更安全,请执行一堆if-else:
Comparator<Integer> ascComparator = (o1, o2) -> {
if (o1 == null && o2 == null) return 0;
else if (o1 == null && o2 != null) return -1;
else if (o1 != null && o2 == null) return 1;
else return Integer.compare(o1, o2);
};
查看了您的尝试后,我意识到这是可行的:
Comparator<Integer> comparator = (o1, o2) -> {
final boolean isDesc = tc.getSortType() == SortType.DESCENDING;
if (o1 == null && o2 == null) return 0;
else if (o1 == null && o2 != null) return isDesc ? -1 : 1;
else if (o1 != null && o2 == null) return isDesc ? 1 : -1;
else return Integer.compare(o1, o2);
};