JavaFX TableView Ignore empty cells when sorting
I have problems when sorting columns when there are empty cells.
I created a new Comparator for my codeMed column:
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;
}
});
At first, it seems to work fine:
But if I decide to sort a different column then sort the codeMed column this happens:
I imagine the error is in the Comparator but I don't know what is the problem.
EDIT:
I want that the null values will always be at the bottom of the column.
I tried something like that:
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;
But it doesn't work :/ (Maybe because of the problem that Slaw suggests)
My solution:
Thank you very much Jai, I adapt your code just because I want to use it for 2 different collumns:
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);
}
};
java javafx tableview
add a comment |
I have problems when sorting columns when there are empty cells.
I created a new Comparator for my codeMed column:
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;
}
});
At first, it seems to work fine:
But if I decide to sort a different column then sort the codeMed column this happens:
I imagine the error is in the Comparator but I don't know what is the problem.
EDIT:
I want that the null values will always be at the bottom of the column.
I tried something like that:
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;
But it doesn't work :/ (Maybe because of the problem that Slaw suggests)
My solution:
Thank you very much Jai, I adapt your code just because I want to use it for 2 different collumns:
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);
}
};
java javafx tableview
add a comment |
I have problems when sorting columns when there are empty cells.
I created a new Comparator for my codeMed column:
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;
}
});
At first, it seems to work fine:
But if I decide to sort a different column then sort the codeMed column this happens:
I imagine the error is in the Comparator but I don't know what is the problem.
EDIT:
I want that the null values will always be at the bottom of the column.
I tried something like that:
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;
But it doesn't work :/ (Maybe because of the problem that Slaw suggests)
My solution:
Thank you very much Jai, I adapt your code just because I want to use it for 2 different collumns:
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);
}
};
java javafx tableview
I have problems when sorting columns when there are empty cells.
I created a new Comparator for my codeMed column:
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;
}
});
At first, it seems to work fine:
But if I decide to sort a different column then sort the codeMed column this happens:
I imagine the error is in the Comparator but I don't know what is the problem.
EDIT:
I want that the null values will always be at the bottom of the column.
I tried something like that:
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;
But it doesn't work :/ (Maybe because of the problem that Slaw suggests)
My solution:
Thank you very much Jai, I adapt your code just because I want to use it for 2 different collumns:
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);
}
};
java javafx tableview
java javafx tableview
edited Nov 14 '18 at 21:38
Couldosh
asked Nov 14 '18 at 3:17
CouldoshCouldosh
549
549
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
I'm surprised it even worked once. This is what I think would work well:
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);
}
});
This would assume any null
value is treated as if it represents the largest possible int
value. This would force it to move to the bottom of the list in an ascending sorted column, or at the top if it is in a descending sorted column. If the reverse is desired, switch Integer.MAX_VALUE
to Integer.MIN_VALUE
.
What you did doesn't work because you have violated this:
The implementor must ensure that sgn(compare(x, y)) == -sgn(compare(y,
x)) for all x and y. (This implies that compare(x, y) must throw an
exception if and only if compare(y, x) throws an exception.)
An example of this violation is when o1
is 5
and o2
is null
. In this case, compare(o1, o2)
returns -1
and compare(o2, o1)
returns -1
as well. One of them should return positive value while the other negative value, or both must return 0
.
Update
This is what you need.
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)));
Also, I would want to point out that while using Integer.MIN_VALUE
and Integer.MAX_VALUE
should work most of the time, there is a much higher risk of integer underflow and overflow problem, which I'm not sure if it's a problem for using comparators and comparables.
If you want to be more safe, then do a bunch of 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);
};
Update again
After looking at what you attempted, I realized that this works:
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);
};
Thank you for you response. Is there a way to always have the null values at the bottom?
– Couldosh
Nov 14 '18 at 3:49
I'm not sure the magnitude of the return value matters, only if it's negative, zero, or positive. @Couldosh Return results that say nulls are greater than non-nulls and the nulls will go towards the bottom when sorted.
– Slaw
Nov 14 '18 at 4:07
I edited my question with a try to always have te null values at the bottom
– Couldosh
Nov 14 '18 at 4:55
@Couldosh Updated answer.
– Jai
Nov 14 '18 at 6:38
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53292696%2fjavafx-tableview-ignore-empty-cells-when-sorting%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
I'm surprised it even worked once. This is what I think would work well:
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);
}
});
This would assume any null
value is treated as if it represents the largest possible int
value. This would force it to move to the bottom of the list in an ascending sorted column, or at the top if it is in a descending sorted column. If the reverse is desired, switch Integer.MAX_VALUE
to Integer.MIN_VALUE
.
What you did doesn't work because you have violated this:
The implementor must ensure that sgn(compare(x, y)) == -sgn(compare(y,
x)) for all x and y. (This implies that compare(x, y) must throw an
exception if and only if compare(y, x) throws an exception.)
An example of this violation is when o1
is 5
and o2
is null
. In this case, compare(o1, o2)
returns -1
and compare(o2, o1)
returns -1
as well. One of them should return positive value while the other negative value, or both must return 0
.
Update
This is what you need.
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)));
Also, I would want to point out that while using Integer.MIN_VALUE
and Integer.MAX_VALUE
should work most of the time, there is a much higher risk of integer underflow and overflow problem, which I'm not sure if it's a problem for using comparators and comparables.
If you want to be more safe, then do a bunch of 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);
};
Update again
After looking at what you attempted, I realized that this works:
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);
};
Thank you for you response. Is there a way to always have the null values at the bottom?
– Couldosh
Nov 14 '18 at 3:49
I'm not sure the magnitude of the return value matters, only if it's negative, zero, or positive. @Couldosh Return results that say nulls are greater than non-nulls and the nulls will go towards the bottom when sorted.
– Slaw
Nov 14 '18 at 4:07
I edited my question with a try to always have te null values at the bottom
– Couldosh
Nov 14 '18 at 4:55
@Couldosh Updated answer.
– Jai
Nov 14 '18 at 6:38
add a comment |
I'm surprised it even worked once. This is what I think would work well:
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);
}
});
This would assume any null
value is treated as if it represents the largest possible int
value. This would force it to move to the bottom of the list in an ascending sorted column, or at the top if it is in a descending sorted column. If the reverse is desired, switch Integer.MAX_VALUE
to Integer.MIN_VALUE
.
What you did doesn't work because you have violated this:
The implementor must ensure that sgn(compare(x, y)) == -sgn(compare(y,
x)) for all x and y. (This implies that compare(x, y) must throw an
exception if and only if compare(y, x) throws an exception.)
An example of this violation is when o1
is 5
and o2
is null
. In this case, compare(o1, o2)
returns -1
and compare(o2, o1)
returns -1
as well. One of them should return positive value while the other negative value, or both must return 0
.
Update
This is what you need.
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)));
Also, I would want to point out that while using Integer.MIN_VALUE
and Integer.MAX_VALUE
should work most of the time, there is a much higher risk of integer underflow and overflow problem, which I'm not sure if it's a problem for using comparators and comparables.
If you want to be more safe, then do a bunch of 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);
};
Update again
After looking at what you attempted, I realized that this works:
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);
};
Thank you for you response. Is there a way to always have the null values at the bottom?
– Couldosh
Nov 14 '18 at 3:49
I'm not sure the magnitude of the return value matters, only if it's negative, zero, or positive. @Couldosh Return results that say nulls are greater than non-nulls and the nulls will go towards the bottom when sorted.
– Slaw
Nov 14 '18 at 4:07
I edited my question with a try to always have te null values at the bottom
– Couldosh
Nov 14 '18 at 4:55
@Couldosh Updated answer.
– Jai
Nov 14 '18 at 6:38
add a comment |
I'm surprised it even worked once. This is what I think would work well:
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);
}
});
This would assume any null
value is treated as if it represents the largest possible int
value. This would force it to move to the bottom of the list in an ascending sorted column, or at the top if it is in a descending sorted column. If the reverse is desired, switch Integer.MAX_VALUE
to Integer.MIN_VALUE
.
What you did doesn't work because you have violated this:
The implementor must ensure that sgn(compare(x, y)) == -sgn(compare(y,
x)) for all x and y. (This implies that compare(x, y) must throw an
exception if and only if compare(y, x) throws an exception.)
An example of this violation is when o1
is 5
and o2
is null
. In this case, compare(o1, o2)
returns -1
and compare(o2, o1)
returns -1
as well. One of them should return positive value while the other negative value, or both must return 0
.
Update
This is what you need.
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)));
Also, I would want to point out that while using Integer.MIN_VALUE
and Integer.MAX_VALUE
should work most of the time, there is a much higher risk of integer underflow and overflow problem, which I'm not sure if it's a problem for using comparators and comparables.
If you want to be more safe, then do a bunch of 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);
};
Update again
After looking at what you attempted, I realized that this works:
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);
};
I'm surprised it even worked once. This is what I think would work well:
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);
}
});
This would assume any null
value is treated as if it represents the largest possible int
value. This would force it to move to the bottom of the list in an ascending sorted column, or at the top if it is in a descending sorted column. If the reverse is desired, switch Integer.MAX_VALUE
to Integer.MIN_VALUE
.
What you did doesn't work because you have violated this:
The implementor must ensure that sgn(compare(x, y)) == -sgn(compare(y,
x)) for all x and y. (This implies that compare(x, y) must throw an
exception if and only if compare(y, x) throws an exception.)
An example of this violation is when o1
is 5
and o2
is null
. In this case, compare(o1, o2)
returns -1
and compare(o2, o1)
returns -1
as well. One of them should return positive value while the other negative value, or both must return 0
.
Update
This is what you need.
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)));
Also, I would want to point out that while using Integer.MIN_VALUE
and Integer.MAX_VALUE
should work most of the time, there is a much higher risk of integer underflow and overflow problem, which I'm not sure if it's a problem for using comparators and comparables.
If you want to be more safe, then do a bunch of 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);
};
Update again
After looking at what you attempted, I realized that this works:
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);
};
edited Nov 14 '18 at 7:37
answered Nov 14 '18 at 3:39
JaiJai
5,82811231
5,82811231
Thank you for you response. Is there a way to always have the null values at the bottom?
– Couldosh
Nov 14 '18 at 3:49
I'm not sure the magnitude of the return value matters, only if it's negative, zero, or positive. @Couldosh Return results that say nulls are greater than non-nulls and the nulls will go towards the bottom when sorted.
– Slaw
Nov 14 '18 at 4:07
I edited my question with a try to always have te null values at the bottom
– Couldosh
Nov 14 '18 at 4:55
@Couldosh Updated answer.
– Jai
Nov 14 '18 at 6:38
add a comment |
Thank you for you response. Is there a way to always have the null values at the bottom?
– Couldosh
Nov 14 '18 at 3:49
I'm not sure the magnitude of the return value matters, only if it's negative, zero, or positive. @Couldosh Return results that say nulls are greater than non-nulls and the nulls will go towards the bottom when sorted.
– Slaw
Nov 14 '18 at 4:07
I edited my question with a try to always have te null values at the bottom
– Couldosh
Nov 14 '18 at 4:55
@Couldosh Updated answer.
– Jai
Nov 14 '18 at 6:38
Thank you for you response. Is there a way to always have the null values at the bottom?
– Couldosh
Nov 14 '18 at 3:49
Thank you for you response. Is there a way to always have the null values at the bottom?
– Couldosh
Nov 14 '18 at 3:49
I'm not sure the magnitude of the return value matters, only if it's negative, zero, or positive. @Couldosh Return results that say nulls are greater than non-nulls and the nulls will go towards the bottom when sorted.
– Slaw
Nov 14 '18 at 4:07
I'm not sure the magnitude of the return value matters, only if it's negative, zero, or positive. @Couldosh Return results that say nulls are greater than non-nulls and the nulls will go towards the bottom when sorted.
– Slaw
Nov 14 '18 at 4:07
I edited my question with a try to always have te null values at the bottom
– Couldosh
Nov 14 '18 at 4:55
I edited my question with a try to always have te null values at the bottom
– Couldosh
Nov 14 '18 at 4:55
@Couldosh Updated answer.
– Jai
Nov 14 '18 at 6:38
@Couldosh Updated answer.
– Jai
Nov 14 '18 at 6:38
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53292696%2fjavafx-tableview-ignore-empty-cells-when-sorting%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown