简体   繁体   中英

Setting type of ObservableList when using a custom class and Comparator

I am attempting to sort a list of a custom class extending HBox inside a VBox. Everything is working perfectly leaving out the type declarations but I was wondering if there was a way to get rid of the warnings.

public static class FilePane extends HBox {}    

public void sort() {
    int order = orderBy.getSelectionModel().getSelectedIndex();
    Comparator<FilePane> comp = null;
    if(order == 0) {
        comp = Comparator.comparing(FilePane::getFileNameLower);
    } else if(order == 1) {
        comp = Comparator.comparingLong(FilePane::getFileDate);
        comp = comp.reversed();
    } else if(order == 2) {
        comp = Comparator.comparingLong(FilePane::getFileSize);
        comp = comp.reversed();
    } else if(order == 3) {
        comp = Comparator.comparingLong(FilePane::getFileCount);
        comp = comp.reversed();
    } else if(order == 4) {
        comp = Comparator.comparing(FilePane::getDirectory);
        comp = comp.reversed();
    }
    ObservableList list = fileList.getChildren();
    FXCollections.sort(list, comp);
}

Trying to set list to ObservableList<FilePane> gives an error telling me it should be set to <Node> since that's what getChildren() returns. Setting it to <Node> does not work and FXCollections.sort(list, comp); gives an error that FilePane will not work because:

The method sort(ObservableList<T>, Comparator<? super T>) in the type FXCollections is not applicable for the arguments (ObservableList<Node>, Comparator<FilePane>)

FilePane extends HBox which should be considered a Node? Comparator's type can't be set to Node because it needs to have the class to compare with. Casting with ObservableList<FilePane> list = (ObservableList<FilePane>) fileList.getChildren(); tells me that it can't do that so it isn't an option.

Should I just ignore the type warnings since it works fine without them? Is there a way to set the VBox's children to a ObservableList<FilePane> ?

If getChildren() returns a list of Node s, then you need the list to be a list of Node s. Let's start there and work backwards.

ObservableList<Node> list = fileList.getChildren();

Okay. If that's the list, then how do we get the sort() call to compile? The answer is that the comparator must be a Comparator<Node> and not a Comparator<FilePane> .

But that's no good, right? Because then we can't use those really slick FilePane:: method references. Hold on there, partner. Not so fast. Isn't there some way to leave that code alone and still make sort() happy?

There is. Let's leave comp alone. It can stay as a Comparator<FilePane> . What we need to do is convert it into a Comparator<Node> some how.

FXCollections.sort(list, convertSomeHow(comp));

How do we convert it? Well, sort() is going to pass the comparator Node s. The comparator we have wants FilePane s. So all we need to do is get a cast in there and then defer to comp . Something like this:

FXCollections.sort(list, Comparator.comparing(node -> (FilePane) node, comp));

Or:

FXCollections.sort(list, Comparator.comparing(FilePane.class::cast, comp));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM