@Beta
  public static <T> java.util.Optional<T> findLast(Stream<T> stream) {
    class OptionalState {
      boolean set = false;
      T value = null;

      void set(@Nullable T value) {
        this.set = true;
        this.value = value;
      }

      T get() {
        checkState(set);
        return value;
      }
    }
    OptionalState state = new OptionalState();

    Deque<Spliterator<T>> splits = new ArrayDeque<>();
    splits.addLast(stream.spliterator());

    while (!splits.isEmpty()) {
      Spliterator<T> spliterator = splits.removeLast();

      if (spliterator.getExactSizeIfKnown() == 0) {
        continue; // drop this split
      }

      // Many spliterators will have trySplits that are SUBSIZED even if they are not themselves
      // SUBSIZED.
      if (spliterator.hasCharacteristics(Spliterator.SUBSIZED)) {
        // we can drill down to exactly the smallest nonempty spliterator
        while (true) {
          Spliterator<T> prefix = spliterator.trySplit();
          if (prefix == null || prefix.getExactSizeIfKnown() == 0) {
            break;
          } else if (spliterator.getExactSizeIfKnown() == 0) {
            spliterator = prefix;
            break;
          }
        }

        // spliterator is known to be nonempty now
        spliterator.forEachRemaining(state::set);
        return java.util.Optional.of(state.get());
      }

      Spliterator<T> prefix = spliterator.trySplit();
      if (prefix == null || prefix.getExactSizeIfKnown() == 0) {
        // we can't split this any further
        spliterator.forEachRemaining(state::set);
        if (state.set) {
          return java.util.Optional.of(state.get());
        }
        // fall back to the last split
        continue;
      }
      splits.addLast(prefix);
      splits.addLast(spliterator);
    }
    return java.util.Optional.empty();
  }
@Beta
  public static <T> java.util.Optional<T> findLast(Stream<T> stream) {
    class OptionalState {
      boolean set = false;
      T value = null;

      void set(@Nullable T value) {
        this.set = true;
        this.value = value;
      }

      T get() {
        checkState(set);
        return value;
      }
    }
    OptionalState state = new OptionalState();

    Deque<Spliterator<T>> splits = new ArrayDeque<>();
    splits.addLast(stream.spliterator());

    while (!splits.isEmpty()) {
      Spliterator<T> spliterator = splits.removeLast();

      if (spliterator.getExactSizeIfKnown() == 0) {
        continue; 
      }

      
      
      if (spliterator.hasCharacteristics(Spliterator.SUBSIZED)) {
        
        while (true) {
          Spliterator<T> prefix = spliterator.trySplit();
          if (prefix == null || prefix.getExactSizeIfKnown() == 0) {
            break;
          } else if (spliterator.getExactSizeIfKnown() == 0) {
            spliterator = prefix;
            break;
          }
        }

        
        spliterator.forEachRemaining(state::set);
        return java.util.Optional.of(state.get());
      }

      Spliterator<T> prefix = spliterator.trySplit();
      if (prefix == null || prefix.getExactSizeIfKnown() == 0) {
        
        spliterator.forEachRemaining(state::set);
        if (state.set) {
          return java.util.Optional.of(state.get());
        }
        
        continue;
      }
      splits.addLast(prefix);
      splits.addLast(spliterator);
    }
    return java.util.Optional.empty();
  }
@ Beta public static < T > java . util . Optional < T > findLast ( Stream < T > stream ) { class OptionalState { boolean set = false ; T value = null ; void set ( @ Nullable T value ) { this . set = true ; this . value = value ; } T get ( ) { checkState ( set ) ; return value ; } } OptionalState state = new OptionalState ( ) ; Deque < Spliterator < T > > splits = new ArrayDeque <> ( ) ; splits . addLast ( stream . spliterator ( ) ) ; while ( ! splits . isEmpty ( ) ) { Spliterator < T > spliterator = splits . removeLast ( ) ; if ( spliterator . getExactSizeIfKnown ( ) == 0 ) { continue ; // drop this split } // Many spliterators will have trySplits that are SUBSIZED even if they are not themselves // SUBSIZED. if ( spliterator . hasCharacteristics ( Spliterator . SUBSIZED ) ) { // we can drill down to exactly the smallest nonempty spliterator while ( true ) { Spliterator < T > prefix = spliterator . trySplit ( ) ; if ( prefix == null || prefix . getExactSizeIfKnown ( ) == 0 ) { break ; } else if ( spliterator . getExactSizeIfKnown ( ) == 0 ) { spliterator = prefix ; break ; } } // spliterator is known to be nonempty now spliterator . forEachRemaining ( state :: set ) ; return java . util . Optional . of ( state . get ( ) ) ; } Spliterator < T > prefix = spliterator . trySplit ( ) ; if ( prefix == null || prefix . getExactSizeIfKnown ( ) == 0 ) { // we can't split this any further spliterator . forEachRemaining ( state :: set ) ; if ( state . set ) { return java . util . Optional . of ( state . get ( ) ) ; } // fall back to the last split continue ; } splits . addLast ( prefix ) ; splits . addLast ( spliterator ) ; } return java . util . Optional . empty ( ) ; }
Returns the last element of the specified stream, or {@link java.util.Optional#empty} if the
stream is empty.

<p>Equivalent to {@code stream.reduce((a, b) -> b)}, but may perform significantly better. This
method's runtime will be between O(log n) and O(n), performing better on <a
href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a>
streams.

<p>If the stream has nondeterministic order, this has equivalent semantics to {@link
Stream#findAny} (which you might as well use).

@see Stream#findFirst()
@throws NullPointerException if the last element of the stream is null
Returns the last element of the specified stream or { @link java . util . Optional#empty } if the stream is empty .