Reputation: 2171
the expression this.apply(stringValue)
returns true
on a lambda expression j8Test.PerformChange$$Lambda$2/284720968@2f4d3709
Why does it return true and not false. And why doest it return actually anything at all? (I am not talking about all other objects of type PerformChangeImpl)
private final List<PerformChange> performChangeList = Arrays.asList(
new PerformChangeImpl("1"),
new PerformChangeImpl("2"),
new PerformChangeImpl("3")
);
@FunctionalInterface
interface PerformChange extends Function<String, Boolean> {
default PerformChange performChange(PerformChange input) {
System.out.println("1 this: " + this);
System.out.println("2 input: " + input);
return stringValue -> {
System.out.println("\n3 this: " + this);
System.out.println("4 input: " + input);
if (this.apply(stringValue)) {
System.out.println("5 this: " + this);
return input.apply(stringValue);
}
return false;
};
}
}
class PerformChangeImpl implements PerformChange {
private final String value;
public PerformChangeImpl(String value) {
this.value = value;
}
@Override
public Boolean apply(String string) {
System.out.println("\n6: " + this);
System.out.println("7: " + string);
return true;
}
@Override
public String toString() {
return "obj id: " + value;
}
}
and
private void executePerformChanges() {
System.out.println(performChangeList.stream()
.reduce(PerformChange::performChange)
.orElse(new PerformChangeImpl("4"))
.apply("test"));
}
result in
1 this: obj id: 1
2 input: obj id: 2
1 this: j8Test.PerformChange$$Lambda$2/284720968@2f4d3709
2 input: obj id: 3
3 this: j8Test.PerformChange$$Lambda$2/284720968@2f4d3709
4 input: obj id: 3
3 this: obj id: 1
4 input: obj id: 2
6: obj id: 1
7: test
5 this: obj id: 1
6: obj id: 2
7: test
5 this: j8Test.PerformChange$$Lambda$2/284720968@2f4d3709
6: obj id: 3
7: test
true
Process finished with exit code 0
Upvotes: 3
Views: 1721
Reputation: 49606
You've got two implementations of PerformChange
:
PerformChangeImpl
which functional method apply
always returns true
. There is no chance to get false
.str -> apply(str) && input.apply(str)
which you are generating in performChange
(I simplified it a bit). There is a chance to get false
if either apply(str)
or input.apply(str)
returns false
.Since performChangeList
contains only PerformChangeImpl
instances, the generated lambda could be simplified to input.apply(str)
, In other words, the method would look like
default PerformChange performChange(PerformChange input) {
// str -> apply(str) && input.apply(str)
// str -> true && input.apply(str)
// str -> input.apply(str)
// input::apply
// input
return input;
}
and the resulting true
is expected for any given String
as long as performChangeList
is populated exclusively with PerformChangeImpl
objects.
As a side note, Function<String, Boolean>
is simply Predicate<String>
and it's better to use the latter.
@FunctionalInterface
interface PerformChange extends Predicate<String> { ... }
class PerformChangeImpl implements PerformChange {
@Override
public boolean test(String string) { ... }
}
Upvotes: 2
Reputation: 140427
Here:
public Boolean apply(String string) {
...
Your class PerformChangeImpl
overrides the apply()
method. That is the core of the Function
interface.
And in the end, your code calls:
.apply("test"))
And the very last statement within apply()
is:
return true;
The method returns true
, because you told it to do so. So you should either change that method body to return true
/ false
based on some condition, or you shouldn't be calling apply()
in the end.
And note: this becomes really obvious from the print statements. In the end, you get 6
and 7
, which you print within the apply()
of the PerformChangeImpl
class.
Also note: your defaulted method does:
if(this.apply(stringValue)) {
That calls apply()
on the "surrounding" PerformChangeImpl
... and will return true
.
Upvotes: 4