In this question, I am required to write a findMatch method that takes in a "stream" (IFL is meant to mimic a stream) and finds the first element of the stream that passes a Predicate. My attempt is as follows:
import java.util.function.Predicate;
import java.util.Optional;
import java.util.ArrayList;
import java.util.List;
class IFL<T> {
Supplier<T> head;
Supplier<IFL<T>> tail;
IFL(Supplier<T> head, Supplier<IFL<T>> tail) {
this.head = head;
this.tail = tail;
}
static <T> IFL<T> of(List<? extends T> list) {
return new IFL<T>(
() -> list.get(0),
() -> IFL.of(list.subList(1, list.size()))) {
};
}
Optional<T> findMatch(Predicate<? super T> predicate) {
if (predicate.test(head.get())) {
return Optional.of(this.head.get());
} else {
if (this.tail.get().findMatch(predicate).isPresent()) {
return this.tail.get().findMatch(predicate);
}
return Optional.empty();
}
}
}
The problem I am facing is that the else
block in my findMatch method seems to only run the return
statement instead of recursively calling itself like i believe it should. Is there anyway to ensure that it does?
Update: i have gotten the code to work for the second line of input. However, running the third line of input produces an IndexOutOfBoundsException
in jshell.
The input is as follows
IFL<String> list = IFL.of(Arrays.asList("three", "little", "pigs"))
list.findMatch(str -> str.length() == 6)
list.findMatch(str -> str.length() < 4)
You can do like this:
By checking list size in the constructor and also checking nullity for this.head
in the findMatch()
method;
You don't need to check if (this.tail.get().findMatch(predicate).isPresent())
and then call again findMatch
method.
class IFL<T> {
Supplier<T> head;
Supplier<IFL<T>> tail;
IFL(Supplier<T> head, Supplier<IFL<T>> tail) {
this.head = head;
this.tail = tail;
}
static <T> IFL<T> of(List<? extends T> list) {
if (list.isEmpty())
return new IFL<>(null, null);
return new IFL<T>(
() -> list.get(0),
() -> IFL.of(list.subList(1, list.size()))) {
};
}
Optional<T> findMatch(Predicate<? super T> predicate) {
if (this.head == null)
return Optional.empty();
return predicate.test(head.get()) ?
Optional.of(this.head.get()) :this.tail.get().findMatch(predicate);
}
}