Gatherers -- conditionalWindowFixed?

Viktor Klang viktor.klang at oracle.com
Wed Jan 10 13:33:45 UTC 2024


Hi David!

Apologies for the late reply, there's been lots of catching up to do after the holidays.

>I'm really excited for what this will enable for us.

I'm really glad to hear that 🙂

>It is very much appreciated.

👍

> Could we add one more method for a conditionalWindowFixed? We would need to pass in some Predicate<T>. If the predicate returns true, create a list (if it does not already exist) then add the element to it. If the predicate returns false while the list is empty, then just move along to the next. Else if the predicate returns false while the list is non empty, pass the list down into the stream. So, you end up with Stream<T> -----> Stream<List<T>>.

What ends up under Gatherers.* does require careful triaging, ideally by first seeing user-created implementations being heavily used/useful, then potential candidate for Gatherers.*, and then at the end it might end up in Stream as a dedicated method.

By virtue of the Gatherers API, it seems pretty straight-forward for you to implement what you describe, and personally I'd probably call it something like windowBy.

Just typing this up as I write this reply, it could look something like this:

<TR> Gatherer<TR, ?, List<TR>> windowBy(Predicate<TR> includeInCurrentWindow) {
  class State {
    ArrayList<TR> window;

    boolean integrate(TR element, Gatherer.Downstream<? super List<TR>> downstream) {
      if (window != null && !includeInCurrentWindow.test(element)) {
        var result = Collections.unmodifiableList(window);
        window = null;
        if (!downstream.push(result))
          return false;
      }

      if (window == null)
        window = new ArrayList<>();

      return window.add(element);
    }

    void finish(Gatherer.Downstream<? super List<TR>> downstream) {
      if (window != null) {
        var result = Collections.unmodifiableList(window);
        window = null;
        downstream.push(result);
      }
    }
  }
  return Gatherer.<TR, State, List<TR>>ofSequential(State::new, State::integrate, State::finish);
}

jshell> Stream.of("header", "value1", "value2", "header", "header", "value 3", "value 4", null).gather(windowBy(Predicate.not("header"::equals))).toList()
$1 ==> [[header, value1, value2], [header], [header, value 3, value 4, null]]


Cheers,
√


Viktor Klang
Software Architect, Java Platform Group
Oracle
________________________________
From: core-libs-dev <core-libs-dev-retn at openjdk.org> on behalf of David Alayachew <davidalayachew at gmail.com>
Sent: Wednesday, 10 January 2024 07:05
To: core-libs-dev at openjdk.org <core-libs-dev at openjdk.org>
Subject: Gatherers -- conditionalWindowFixed?

Hello Core Libs Dev Team,

I have been reading through JEP 461 (https://openjdk.org/jeps/461) about Gatherers, and I'm really excited for what this will enable for us.

By far, the most important functionality that this API facilitates is the ability to create windows. Anytime I needed a window, I was basically forced to use a for loop. Now, the 2 most common window cases are being handed to us for free. It is very much appreciated.

Could we add one more method for a conditionalWindowFixed? We would need to pass in some Predicate<T>. If the predicate returns true, create a list (if it does not already exist) then add the element to it. If the predicate returns false while the list is empty, then just move along to the next. Else if the predicate returns false while the list is non empty, pass the list down into the stream. So, you end up with Stream<T> -----> Stream<List<T>>.

The reason I think this is worth adding is because it facilitates a really common use case. We may not want all windows to be the same size.

Is this something worth adding to the Gatherers API?

Thank you for your time and help!
David Alayachew
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/core-libs-dev/attachments/20240110/ee085203/attachment.htm>


More information about the core-libs-dev mailing list