Collectors lambda return observable list
Asked Answered
H

1

11

Is it possible for Collectors to return me a ObservableArrayList? A little like this:

ObservableList<String> newList = list.stream().
        filter(x -> x.startsWith("a").
        collect(Collectors.toCollection(ObservableArrayList::new));
Hageman answered 21/11, 2015 at 22:49 Comment(2)
You just did it, didn't you?Allyn
@Allyn Nope, there is no constructor for ObservableArrayList (it isn't event a class actually)Postfix
P
27

ObservableLists are created with the static factories from the FXCollections class.

As noted by Louis Wasserman in the comments, this can be done using toCollection:

ObservableList<String> newList = 
        list.stream()
            .filter(x -> x.startsWith("a"))
            .collect(Collectors.toCollection(FXCollections::observableArrayList));

You could also do the following, which first collects the stream into a List and then wraps it inside an ObservableList.

ObservableList<String> newList = 
        list.stream()
            .filter(x -> x.startsWith("a"))
            .collect(Collectors.collectingAndThen(toList(), l -> FXCollections.observableArrayList(l)));

(which unfortunately enough does not compile on Eclipse Mars 4.5.1 but compiles fine on javac 1.8.0_60).

Another possibility is to create a custom Collector for this. This has the advantage that there is no need to first use a List. The elements are directly collected inside a ObservableList.

ObservableList<String> newList = 
        list.stream()
            .filter(x -> x.startsWith("a"))
            .collect(Collector.of(
                FXCollections::observableArrayList,
                ObservableList::add,
                (l1, l2) -> { l1.addAll(l2); return l1; })
            );
Postfix answered 21/11, 2015 at 23:1 Comment(7)
that last expression looks nasty. ThanksHageman
@Hageman The static imports help a bit. Also, I added a second possibility which does not use an intermediate list.Postfix
Why not just collect(toCollection(FXCollections::observableArrayList)), which solves both problems?Joplin
Ah wonderful, works like a charm. This lambda stuff is not really my thing (yet) :D. I'd pick a for loop just out of reflexHageman
@LouisWasserman Yes, you're right. Weirdly it didn't cross my mind. Is it ok if I edit that in? You could post your own answerPostfix
@Postfix I made a typo. How do I know what to place in front of the :: and after it. It seems to be a bunch of unordered rules.Hageman
Shouldn't it be .collect(Collectors.toCollection(FXCollections::observableArrayList)) in the last line? I think Collectors is missing there.Incumbency

© 2022 - 2024 — McMap. All rights reserved.