I'm trying to understand the syntax in the create method of the following example:
import java.math.BigDecimal;
import java.util.function.Consumer;
import java.util.function.Function;
#FunctionalInterface
interface Before<T, R> extends Function<Consumer<T>, Function<Function<T, R>, Function<T, R>>> {
static <T, R> Before<T, R> create() {
return before -> function -> argument -> {
before.accept(argument);
return function.apply(argument);
};
}
static <T, R> Function<T, R> decorate(Consumer<T> before, Function<T, R> function) {
return Before.<T, R>create().apply(before).apply(function);
}
}
public class BeforeExample {
void demo() {
System.out.println("----------------------------------");
System.out.println("Starting BEFORE combinator demo...");
System.out.println("----------------------------------");
Function<BigDecimal, String> addTax = this::addTax;
Consumer<BigDecimal> before = this::before;
Function<BigDecimal, String> addTaxDecorated = Before.decorate(before, addTax);
BigDecimal argument = new BigDecimal("100");
String result = addTaxDecorated.apply(argument);
System.out.println("Done - Result is " + result);
System.out.println();
}
private void before(BigDecimal argument) {
System.out.println("BEFORE: Argument is " + argument);
}
private String addTax(BigDecimal amount) {
System.out.println("Adding heavy taxes to our poor citizen...");
return "$" + amount.multiply(new BigDecimal("1.22"));
}
}
Can someone please explain:
what is going on in the return before -> function -> argument -> {...} block and how the variables before, function and argument become known without seemingly being passed into create's signature, as well as
what the multiple -> signify.
Thank you.
what is going on in the return before -> function -> argument -> {...}
block and how the variables before, function and argument become known
without seemingly being passed in
The following piece of code can help you understand the block and the usage of variables within:
static <T, R> Before<T, R> create() {
return new Before<T, R>() {
#Override
public Function<Function<T, R>, Function<T, R>> apply(Consumer<T> before) {
return new Function<Function<T, R>, Function<T, R>>() {
#Override
public Function<T, R> apply(Function<T, R> function) {
return new Function<T, R>() {
#Override
public R apply(T argument) {
before.accept(argument);
return function.apply(argument);
}
};
}
};
}
};
}
what the multiple -> signify.
The lambda representation for each of those functional interfaces combined to represent the implementation of create method.
I am creating a 'SpecialList' and am require to implement the map function. The list should be lazy, and will only produce values when evaluated.
toString() returns "?" if the value is not yet available; returns the string representation of the value otherwise.
get() called when the contents is needed. If the value is already available, return that value; otherwise, compute the value and return it. The computation should only be done once for the same value.
Here's what I have:
public <U> SpecialList<U> map(Function<T, U> mapper) {
if (!this.isAvailable) {
return new SpecialList<U>(this.supplier);
}
return new SpecialList<U>(mapper, value);
}
// private constructor
private SpecialList(CachedSupplier<T> s) {
this.supplier = s;
this.isAvailable = false;
}
However, it is telling me that there's no valid constuctor because T cannot be converted to U.
SpecialList.java:65: error: no suitable constructor found for SpecialList(SpecialList<T>.CachedSupplier<T>)
return new SpecialList<U>(this.supplier);
^
constructor SpecialList.SpecialList(U) is not applicable
(argument mismatch; SpecialList<T>.CachedSupplier<T> cannot be converted to U)
constructor SpecialList.SpecialList(Supplier<U>) is not applicable
(argument mismatch; SpecialList<T>.CachedSupplier<T> cannot be converted to Supplier<U>)
Doesn't the 'U' become a T when returned?
How do I go about solving this? I am still a little unclear about the method level generic types. But I was told that I need to add the < U > for my map method.
Below is my code in full:
class SpecialList<T> {
class CachedSupplier<T> {
private Supplier<? extends T> supplier;
private T value;
boolean isAvailable;
public CachedSupplier(Supplier<? extends T> supplier) {
this.supplier = supplier;
}
public T get() {
if (!isAvailable) {
value = supplier.get();
isAvailable = true;
}
return value;
}
}
private CachedSupplier<T> supplier;
private T value;
boolean isAvailable;
private SpecialList(T value) {
this.value = value;
this.isAvailable = true;
}
private SpecialList(Supplier<T> s) {
this.supplier = new CachedSupplier<T>(s);
this.isAvailable = false;
}
private SpecialList(CachedSupplier<T> s) {
this.supplier = s;
this.isAvailable = false;
}
private <R> SpecialList(Function<T, R> mapper, T v) {
this.supplier = new CachedSupplier<T>(() -> mapper.apply(v));
this.isAvailable = false;
}
public static <T> SpecialList<T> of(T value) {
return new SpecialList<>(value);
}
public static <T> SpecialList<T> of(Supplier<T> supplier) {
return new SpecialList<>(supplier);
}
public <R> SpecialList<R> map(Function<? super T,? extends R> mapper) {
if (!this.isAvailable) {
return new SpecialList<>(this.supplier);
}
return new SpecialList<R>(mapper, value);
}
public T get() {
if(this.isAvailable) {
return this.value;
} else {
this.value = this.supplier.get();
this.isAvailable = true;
return this.value;
}
}
}
I am still a little confused with Generic Types etc. so please let me know if there's anything odd/I can improve!
Thanks
According to the code you posted, there is a compile-time error in one of the constructors for class SpecialList...
private <R> SpecialList(Function<T, R> mapper, T v) {
this.supplier = new CachedSupplier<T>(() -> mapper.apply(v));
this.isAvailable = false;
}
Firstly, in the code you posted, there is no constructor in inner class CachedSupplier that takes a Function parameter, so you need to add one with this signature:
public <R> CachedSupplier(Function<T, R> mapper)
And the second problem with the SpecialList constructor is the lambda expression. Abstract method apply in interface Function has a parameter, which your lambda expression is missing. So the constructor code should be:
private <R> SpecialList(Function<T, R> mapper, T v) {
this.supplier = new CachedSupplier<T>((v) -> mapper.apply(v));
this.isAvailable = false;
}
The problem is your map function is changing the SpecialList type parameter from T to R. But in the fragment highlited by compiler you return still SpecialList.
Things you can do:
If you are not planning to change the type of elements with your map() function, get rid of R, and replace Function<? super T,? extends R> mapper with Function<? super T,? extends T> mapper. However, this way the mapper would be totaly omited, which might not be the desired behaviuor.
Otherwise, you should pass into your SpecialList constructor a combination of the original supplier and new mapper like so:
return new SpecialList<R>(() -> {
T originalValue = this.supplier.get();
return mapper.apply(originalValue);
};
I think you're doing an overkill by checking isAvailable in both, the SpecialList and the CachedSupplier. It seems enough to me to do so in the CachedSupplier and reduce the members of SpecialList to just the supplier (which is, when the value is available, simply a value-getter without additional costly evaluations). And in the constructors you make sure that the supplier is a cached one, when needed (i.e. when you don't have the value yet).
So here's my suggestion. Further comments are directly in the source code (which compiles now without errors or warnings):
class SpecialList<T> {
static class CachedSupplier<R> implements Supplier<R> {
/* R is a priori an idependent parameter. If you call it T again, then you get a warning
* that the original T is hidden within the new nested class (though it wouldn't really matter here),
* as one doesn't need to refer to it. I made it static, as you don't need an instance to define it. */
private Supplier<? extends R> supplier;
private R value;
boolean isAvailable;
public CachedSupplier(Supplier<? extends R> supplier) {
this.supplier = supplier;
this.isAvailable = false;
}
#Override
public R get() {
if (!isAvailable) {
value = supplier.get();
isAvailable = true;
}
return value;
}
}
private Supplier<T> supplier;
private SpecialList(T value) {
/* in this case no lazy evaluation and no caching needed */
this.supplier = () -> value;
}
private SpecialList(Supplier<T> s) {
this.supplier = new CachedSupplier<T>(s);
}
private SpecialList(CachedSupplier<T> s) {
this.supplier = s;
}
private <R> SpecialList(Function<R, T> mapper, R v) {
/* This constructor is not needed anymore in my suggested code.
* I left it simply, in order to show how to fix the type errors related to it.
* if I understood correctly the intentions of this constructor,
* R and T have to be swapped w.r.t the original post.
* This is a constructor that uses an R-value and a mapper R->T to create a SpecialList<T> */
this.supplier = new CachedSupplier<T>(() -> mapper.apply(v));
}
public static <T> SpecialList<T> of(T value) {
return new SpecialList<>(value);
}
public static <T> SpecialList<T> of(Supplier<T> supplier) {
return new SpecialList<>(supplier);
}
public <R> SpecialList<R> map(Function<T, R> mapper) {
/* mapper is here different (opposite direction) than in the last of the constructors.
* Here we have an existing SpecialList containing a value of Type T which will be turned into a
* SpecialList containing a value of type R by applying a mapper T->R after getting the value from
* the original SpecialList */
return new SpecialList<R>(() -> mapper.apply(get()));
}
public T get() {
return this.supplier.get();
}
}
This solution doesn't yet take care of the toString() implementation. When you want to implement also the latter, it might be more natural to make SpecialList a subclass of CachedSupplier (with the additional map- and toString- methods and direct access to isAvailable)
While working with Java 8 Optionals I face following scenario very frequently. I have two Optional objects and then I want to call different methods based on the values (ifPresent) of those Optionals.
Here is an example:
void example(Optional<String> o1, Optional<String> o2) throws Exception {
if (o1.isPresent() && o2.isPresent()) {
handler1(o1.get(), o2.get());
} else if (o1.isPresent()) {
handler2(o1.get());
} else if (o2.isPresent()) {
handler3(o2.get());
} else {
throw new Exception();
}
}
However, this chain of if-else statements doesn't seem like a proper way of working with Optional (after all, they were added so that you can avoid writing these if-else checks everywhere in your code).
What is the proper way of doing this with Optional objects?
You said that you use such structure frequently, so I propose to introduce a Helper class:
final class BiOptionalHelper<F, S> {
private final Optional<F> first;
private final Optional<S> second;
public BiOptionalHelper(Optional<F> first, Optional<S> second){
this.first = first;
this.second = second;
}
public BiOptionalHelper<F, S> ifFirstPresent(Consumer<? super F> ifPresent){
if (!second.isPresent()) {
first.ifPresent(ifPresent);
}
return this;
}
public BiOptionalHelper<F, S> ifSecondPresent(Consumer<? super S> ifPresent){
if (!first.isPresent()) {
second.ifPresent(ifPresent);
}
return this;
}
public BiOptionalHelper<F, S> ifBothPresent(BiConsumer<? super F, ? super S> ifPresent){
if(first.isPresent() && second.isPresent()){
ifPresent.accept(first.get(), second.get());
}
return this;
}
public <T extends Throwable> void orElseThrow(Supplier<? extends T> exProvider) throws T{
if(!first.isPresent() && !second.isPresent()){
throw exProvider.get();
}
}
}
Which then may be used in a way like this:
new BiOptionalHelper<>(o1, o2)
.ifBothPresent(this::handler1)
.ifFirstPresent(this::handler2)
.ifSecondPresent(this::handler3)
.orElseThrow(Exception::new);
Though, this just moves your problem into a separate class.
Note: above code may be refactored to not use Optional and isPresent() checks at all. And just use null for first and second and replace isPresent() with null-checks.
As it is generally a bad design to store Optional in fields or accept them as parameters in the first place. As JB Nizet already pointed out in a comment to the question.
Another way it to move that logic into common helper method:
public static <F, S, T extends Throwable> void handle(Optional<F> first, Optional<S> second,
BiConsumer<F, S> bothPresent, Consumer<F> firstPresent,
Consumer<S> secondPresent, Supplier<T> provider) throws T{
if(first.isPresent() && second.isPresent()){
bothPresent.accept(first.get(), second.get());
} else if(first.isPresent()){
firstPresent.accept(first.get());
} else if(second.isPresent()){
secondPresent.accept(second.get());
} else{
throw provider.get();
}
}
Which then could be called like this:
handle(o1, o2, this::handler1, this::handler2, this::handler3, Exception::new);
But it's still kind of messy to be honest.
Disclaimer: My answer is based on Lino's answer - the first part of this answer (BiOptional<T, U>) is a modified version of Lino's BiOptionalHelper, while the second part (BiOptionalMapper<T, U, R>) is my idea for extending this nice pattern.
I like Lino's answer a lot. However, I feel that instead of calling it BiOptionalHelper, it deserves to be simply called BiOptional, provided that:
it gets Optional<T> first() and Optional<T> second() methods
it gets is(First/Second)Present, is(First/Second)OnlyPresent and are(Both/None)Present methods
if(First/Second)Present methods are renamed to if(First/Second)OnlyPresent
it gets ifNonePresent(Runnable action) method
orElseThrow method is renamed to ifNonePresentThrow
Finally (and this is the entirely original part of my answer), I realized this pattern could support not only "handling" (in BiOptional), but also "mapping" (in BiOptionalMapper obtained through BiOptional.mapper()), like that:
BiOptional<String, Integer> biOptional = BiOptional.from(o1, o2);
// handler version
biOptional
.ifBothPresent(this::handleBoth)
.ifFirstOnlyPresent(this::handleFirst)
.ifSecondOnlyPresent(this::handleSecond)
.ifNonePresent(this::performAction);
// mapper version
String result = biOptional.<String>mapper()
.onBothPresent(this::mapBoth)
.onFirstOnlyPresent(this::mapFirst)
.onSecondOnlyPresent(this::mapSecond)
.onNonePresent("default")
.result();
Optional<String> optionalResult = biOptional.<String>mapper()
.onBothPresent(this::mapBoth)
.onNonePresentThrow(IllegalStateException::new)
.optionalResult();
Note that one can either:
call all on*Present mapping methods, and then call R result() (which will throw if result were to be absent), or
call only some of them, and then call Optional<R> optionalResult()
Note also that:
in order to avoid confusion between "handling" and "mapping", the naming convention is as follows:
BiOptional: if*Present
BiOptionalMapper: on*Present
if any of the on*Present methods is called twice, BiOptionalMapper will throw if result were to be overwritten (unlike BiOptional, which can handle multiple if*Present calls)
result cannot be set to null by the mappers provided to on*Present or by calling onNonePresent(R) (Optional<...> should be used as result type R instead)
Here's the source code of the two classes:
final class BiOptional<T, U> {
#Nullable
private final T first;
#Nullable
private final U second;
public BiOptional(T first, U second) {
this.first = first;
this.second = second;
}
public static <T, U> BiOptional<T, U> from(Optional<T> first, Optional<U> second) {
return new BiOptional<>(first.orElse(null), second.orElse(null));
}
public Optional<T> first() {
return Optional.ofNullable(first);
}
public Optional<U> second() {
return Optional.ofNullable(second);
}
public boolean isFirstPresent() {
return first != null;
}
public boolean isSecondPresent() {
return second != null;
}
public boolean isFirstOnlyPresent() {
return isFirstPresent() && !isSecondPresent();
}
public boolean isSecondOnlyPresent() {
return !isFirstPresent() && isSecondPresent();
}
public boolean areBothPresent() {
return isFirstPresent() && isSecondPresent();
}
public boolean areNonePresent() {
return !isFirstPresent() && !isSecondPresent();
}
public BiOptional<T, U> ifFirstOnlyPresent(Consumer<? super T> ifFirstOnlyPresent) {
if (isFirstOnlyPresent()) {
ifFirstOnlyPresent.accept(first);
}
return this;
}
public BiOptional<T, U> ifSecondOnlyPresent(Consumer<? super U> ifSecondOnlyPresent) {
if (isSecondOnlyPresent()) {
ifSecondOnlyPresent.accept(second);
}
return this;
}
public BiOptional<T, U> ifBothPresent(BiConsumer<? super T, ? super U> ifBothPresent) {
if (areBothPresent()) {
ifBothPresent.accept(first, second);
}
return this;
}
public BiOptional<T, U> ifNonePresent(Runnable ifNonePresent) {
if (areNonePresent()) {
ifNonePresent.run();
}
return this;
}
public <X extends Throwable> void ifNonePresentThrow(Supplier<? extends X> throwableProvider) throws X {
if (areNonePresent()) {
throw throwableProvider.get();
}
}
public <R> BiOptionalMapper<T, U, R> mapper() {
return new BiOptionalMapper<>(this);
}
}
and:
final class BiOptionalMapper<T, U, R> {
private final BiOptional<T, U> biOptional;
private R result = null;
BiOptionalMapper(BiOptional<T, U> biOptional) {
this.biOptional = biOptional;
}
public BiOptionalMapper<T, U, R> onFirstOnlyPresent(Function<? super T, ? extends R> firstMapper) {
if (biOptional.isFirstOnlyPresent()) {
setResult(firstMapper.apply(biOptional.first().get()));
}
return this;
}
public BiOptionalMapper<T, U, R> onSecondOnlyPresent(Function<? super U, ? extends R> secondMapper) {
if (biOptional.isSecondOnlyPresent()) {
setResult(secondMapper.apply(biOptional.second().get()));
}
return this;
}
public BiOptionalMapper<T, U, R> onBothPresent(BiFunction<? super T, ? super U, ? extends R> bothMapper) {
if (biOptional.areBothPresent()) {
setResult(bothMapper.apply(biOptional.first().get(), biOptional.second().get()));
}
return this;
}
public BiOptionalMapper<T, U, R> onNonePresent(Supplier<? extends R> supplier) {
if (biOptional.areNonePresent()) {
setResult(supplier.get());
}
return this;
}
public BiOptionalMapper<T, U, R> onNonePresent(R other) {
if (biOptional.areNonePresent()) {
setResult(other);
}
return this;
}
public <X extends Throwable> BiOptionalMapper<T, U, R> onNonePresentThrow(Supplier<? extends X> throwableProvider) throws X {
biOptional.ifNonePresentThrow(throwableProvider);
return this;
}
public R result() {
if (result == null) {
throw new IllegalStateException("Result absent");
}
return result;
}
public Optional<R> optionalResult() {
return Optional.ofNullable(result);
}
private void setResult(R result) {
if (result == null) {
throw new IllegalArgumentException("Null obtained from a mapper");
}
if (this.result != null) {
throw new IllegalStateException("Result already present: " + this.result);
}
this.result = result;
}
}
It doesn’t really answer your question, but since Java 9 I would prefer something along these lines:
o1.ifPresentOrElse(s1 -> {
o2.ifPresentOrElse(s2 -> {
handler1(s1, s2);
}, () -> {
handler2(s1);
});
}, () -> {
o2.ifPresentOrElse(s2 -> {
handler3(s2);
}, () -> {
throw new IllegalArgumentException("Neither was present");
});
});
There’s a rule of thumb about Optional saying not to use isPresent and get. I do use them very occasionally; most often they are better avoided.
To avoid if statements or here if (Optional.isPresent()) you should have a common way to handle the Optional values but it is not the case as according their content you may invoke a function with the functional interface Consumer<String> or BiConsumer<String, String>.
As hint, you may factor the second part but it is not more readable or a better way :
if (o1.isPresent() && o2.isPresent()) {
handler1(o1.get(), o2.get());
} else {
Map<Optional<String>, Consumer<String>> map = new HashMap<>();
map.put(o1, this::handler2);
map.put(o2, this::handler3);
Optional<String> opt = Stream.of(o1, o2)
.filter(Optional::isPresent)
.findFirst()
.orElseThrow(Exception::new);
map.get(opt)
.accept(opt.get());
}
If you have much more Optionals to handle in this way such as this would probably make more sense but still it is a lot of code to write.
A more readable alternative could be to introduce a Rule class that stores the information required to trigger that if required :
public Rule(BiPredicate<Optional<String>, Optional<String>> ruleFunction, Runnable runnableIfApplied) {
this.ruleFunction = ruleFunction;
this.runnable = runnableIfApplied;
}
The BiPredicate<Optional<String>, Optional<String>> represents the matching function and the Runnable is the method to execute if the matching occurs.
You could move the rule execution logic in a Rule static method.
The idea is to make as clear as possible the rule specifications from the client side such as :
void example(Optional<String> o1, Optional<String> o2, Optional<String> o3) throws Exception {
Rule.executeFirstMatchOrFail(o1, o2,
new Rule((opt1, opt2) -> opt1.isPresent() && opt2.isPresent(), () -> handler1(o1.get(), o2.get())),
new Rule((opt1, opt2) -> opt1.isPresent(), () -> handler2(o1.get())),
new Rule((opt1, opt2) -> opt2.isPresent(), () -> handler3(o2.get())));
}
Rule could look like :
public class Rule {
static void executeFirstMatchOrFail(Optional<String> o1, Optional<String> o2, Rule... rules) throws Exception {
for (Rule rule : rules) {
if (rule.apply(o1, o2)) {
return;
}
}
throw new Exception();
}
private Runnable runnable;
private BiPredicate<Optional<String>, Optional<String>> ruleFunction;
public Rule(BiPredicate<Optional<String>, Optional<String>> ruleFunction, Runnable runnableIfApplied) {
this.ruleFunction = ruleFunction;
this.runnable = runnableIfApplied;
}
public boolean apply(Optional<String> o1, Optional<String> o2) {
if (ruleFunction.test(o1,o2)) {
runnable.run();
return true;
}
return false;
}
}
I'm pretty new to Java and following a course to understand it better. In the Test code below we are supposed to be able to create a method that accepts multiple Predicate. I can't seem to get it right. Collections seem logical but they can't be used. so I thought Predicate<T>[] predicates would suffice. But no success there.
public class Utils {
// public static <T> Predicate<T> anyPassPredicate(Predicate<T>[] predicates) {
public static <T> Predicate<T> anyPassPredicate(Collection<Predicate<T>> predicates) {
Predicate<T> pred = predicates.stream().reduce(Predicate::or).orElse(x->false);;
return pred;
}
public static <T> T firstAnyMatch(List<T> list, Predicate<T> predicate) {
for (T element : list) {
if (predicate.test(element)) {
return element;
}
}
return null;
}
}
Test code
public class Test {
public static void main(String[] args) {
List<String> words = Arrays.asList("Jan", "Jos", "Anna", "Pieter", "Johan");
Predicate<String> anyMatch = Utils.anyPassPredicate(s -> s.contains("o"), s -> s.length() > 5);
Utils.firstAnyMatch(words, anyMatch);
}
}
How is it possible to accept multiple Predicate as argument to the method?
In order for a method to accept an unspecified number of arguments of the same type, you need to use varargs, which is specified by an ellipsis
static <T> Predicate<T> anyPassPredicate(Predicate<T>... predicates) {
return Arrays.stream(predicates)
.reduce(Predicate::or)
.orElse(x->false);
}
I've seen some takeWhile implementations for the Java 8 stream API but they all seem to turn the stream into a non-parallel stream. For example this one:
static <T> Spliterator<T> takeWhile(
Spliterator<T> splitr, Predicate<? super T> predicate) {
return new Spliterators.AbstractSpliterator<T>(splitr.estimateSize(), 0) {
boolean stillGoing = true;
#Override public boolean tryAdvance(Consumer<? super T> consumer) {
if (stillGoing) {
boolean hadNext = splitr.tryAdvance(elem -> {
if (predicate.test(elem)) {
consumer.accept(elem);
} else {
stillGoing = false;
}
});
return hadNext && stillGoing;
}
return false;
}
};
}
static <T> Stream<T> takeWhile(Stream<T> stream, Predicate<? super T> predicate) {
return StreamSupport.stream(takeWhile(stream.spliterator(), predicate), false);
}
Here StreamSupport.stream(takeWhile(stream.spliterator(), predicate), false); turns the stream passed to takeWhile into a sequential stream. Is anyone aware of an implementation that supports parallel streams or how can I modify this code to make it maintain/support parallel streams?
If your source is known to be unordered, then the following implementation should work:
static final class UnorderedTakeWhileSpliterator<T> implements Spliterator<T>, Consumer<T>, Cloneable {
private final Predicate<? super T> predicate;
private final AtomicBoolean checked = new AtomicBoolean();
private Spliterator<T> source;
private T cur;
UnorderedTakeWhileSpliterator(Spliterator<T> source, Predicate<? super T> predicate) {
this.predicate = predicate;
this.source = source;
}
#Override
public void accept(T t) {
this.cur = t;
}
#Override
public boolean tryAdvance(Consumer<? super T> action) {
if (!checked.get() && source.tryAdvance(this)) {
if (predicate.test(cur)) {
action.accept(cur);
return true;
} else {
checked.set(true);
}
}
return false;
}
#Override
public Spliterator<T> trySplit() {
Spliterator<T> prefix = source.trySplit();
if(prefix == null) {
return null;
}
if(checked.get()) {
return Spliterators.emptySpliterator();
}
UnorderedTakeWhileSpliterator<T> clone;
try {
clone = (UnorderedTakeWhileSpliterator<T>) clone();
} catch (CloneNotSupportedException e) {
throw new InternalError(e);
}
clone.source = prefix;
return clone;
}
#Override
public long estimateSize() {
return source.estimateSize();
}
#Override
public int characteristics() {
return source.characteristics() & (DISTINCT | SORTED | NONNULL);
}
#Override
public Comparator<? super T> getComparator() {
return source.getComparator();
}
}
Create the stream with the following method:
static <T> Stream<T> takeWhile(Stream<T> stream, Predicate<? super T> predicate) {
return StreamSupport.stream(UnorderedTakeWhileSpliterator<>(stream.spliterator(), predicate), stream.isParallel());
}
Ordered implementation would be much more tricky as it should buffer non-prefixed items and propagate the cancelling to the suffixes. Something like this is implemented in JDK-9 (not as spliterator, but as normal stream operation), but I doubt that even this tricky implementation wins in many cases over sequential stream.