IntelliJ - method reference may change semantics - java

I have following code:
return userService.getAll()
.stream()
.map(User::getRoleName)
.map(roleName -> roleService.findRoleByName(roleName))
.collect(Collectors.toSet());
It seems that roleName -> roleService.findRoleByName(roleName) could be replaced by a method reference (namely a Reference to an instance method of a particular object) however IntelliJ IDEA warns that this may change semantics:
How could it change semantics? Would it change semantics?

If you do not follow the rules of clean functional programming, there may be a change of semantics when you convert a lambda to a method reference.
The difference is that the method reference will be resolved when the stream is being built. But in the lambda expression the code for getting the method can be evaluated in each execution of the lambda.
Here is a short self-contained example for demonstration:
public class Test40 {
public static void main(String[] args) {
Function<Integer, Integer> f2 = n -> 2 * n;
Function<Integer, Integer> f3 = n -> 3 * n;
Function<Integer, Integer>[] funcArray = new Function[1];
funcArray[0] = f2;
Stream.of(1, 2, 3)
.peek(n -> { if (n > 1 ) funcArray[0] = f3; })
.map(funcArray[0]::apply) // Method reference, '::apply' could be omitted
.forEach(System.out::print); // prints 246
System.out.println();
funcArray[0] = f2;
Stream.of(1, 2, 3)
.peek(n -> { if (n > 1 ) funcArray[0] = f3; })
.map(n -> funcArray[0].apply(n)) // Lambda
.forEach(System.out::print); // prints 269
System.out.println();
}
}
How to avoid this problem: Do not use side effects when working with streams. Do not use peek for processing! This method exists mainly to support debugging (have a look at the javadoc).

Related

Lambda expression coding variation for optional.filter

I am trying to experiment with lambda expressions, is there any other way we can write filter ( optional.filter(s -> (s.length() > 4)) )
This is complete working code:
public class Main {
public static void main(String[] args) {
Optional<String> optional = Optional.of("Hello");
System.out.println(optional.filter(s -> (s.length() > 4)).get());
}
}
For example one wrong way is below, though it throws compilation saying "can not resolve method length" but here with this trying to explain kind of variation I am thinking.
optional.filter(length() > 4)
You're trying to introduce syntax that is not allowed in java.
These are the valid syntax:
optional.filter(s -> s.length() > 4)
or:
optional.filter(s -> {
return s.length() > 4;
})
or:
optional.filter(new Predicate<String>() {
#Override
public boolean test(String s) {
return s.length() > 4
}
})
You should prefer the first in this specific case as it's more compact and readable.
If you don't want to write complex operations in the stream chain, you can always define the Function / Predicate / etc separately and just use them. It also increases readability.
For example, you can define a Predicate for you case like below:
Predicate<String> byStrLengthCheck = s -> s.length() > 4;
And use the above Predicate like below:
System.out.println(optional.filter(byStrLengthCheck).get());

How to implement a java.util.function.Predicate as Kotlin lambda?

I need to pass a java.util.function.Predicate to a Java function. How can I implement it as Lambda in Kotlin?
The Java-Function I need to call:
public void foo(Predicate<String> p)
Java Lambda implemenation ✔ :
foo(text-> true)
Kotlin Lambda implemenation ❌:
foo{text:String -> true}
^^^^^^^^^^^^
Type mismatch.
Required: Predicate<String>
Found: (String) → Boolean
Kotlin-Version 1.2.21
Since Kotlin 1.4
foo({text -> true })
or
foo {text -> true}
Before Kotlin 1.4
These variants work:
foo(Predicate {text -> true })
foo(Predicate {true})
foo({true }as Predicate<String>)
If in case want to declare as a property:
private val normal = Predicate<Int> { true }
private val even = Predicate<Int> { it % 2 == 0 }
private val odd = even.negate()
fun main() {
println("Normal count ${get(normal)}")
println("Even count ${get(even)}")
println("Odd count ${get(odd)}")
}
fun get(predicate: Predicate<Int>): Int {
val filter = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).filter { predicate.test(it)}
println(filter)
val map = filter.map { it * 2 }
println(map)
return map.sum()
}
It works fine, here is a test that compiles with a Java List and the filter method that takes a Predicate as parameter:
val test = Arrays.asList("Hello", "Bye", "World!")
println(test)
println(test.filter { it.startsWith("W") })
Is the last sample code (foo{text:String -> true}) your code that does not compile?
Between the braces, your are supposed to pass the implementation of the lambda, not the type/interface of it. This part is inferred for you!
As of Kotlin 1.4, there is support for Single Abstract Method (SAM) conversion for Java interfaces:
https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
From the example in the question, the following works now:
foo { text -> true }

"Double" composition with CompletableFuture

I'm trying to avoid nesting CompletableFuture when combining 2 independent ones with a BiFunction that returns a third one.
Currently, using thenCombine() does not cut it:
// What I have
public CompletableFuture<CompletableFuture<C>> doStuff() {
CompletableFuture<A> aFuture = makeSomeA();
CompletableFuture<B> bFuture = makeSomeB();
CompletableFuture<CompletableFuture<C>> cFuture = aFuture.thenCombine(bFuture, this::makeSomeC);
return cFuture;
}
// What I want
public CompletableFuture<C> doStuff() {
CompletableFuture<A> aFuture = makeSomeA();
CompletableFuture<B> bFuture = makeSomeB();
// obv this method does not exist
CompletableFuture<C> c = aFuture.thenBicompose(bFuture, this::makeSomeC);
}
private CompletableFuture<A> makeSomeA() {...}
private CompletableFuture<B> makeSomeB() {...}
private CompletableFuture<C> makeSomeC(A a, B b) {...}
I'm basically trying to find a way that looks like haskell if there was a CompletableFuture monad:
doStuff :: CompletableFuture C
doStuff = do
a <- makeSomeA
b <- makeSomeB
makeSomeC a b
makeSomeA :: CompletableFuture A
makeSomeB :: CompletableFuture B
makeSomeC :: A -> B -> CompletableFuture C
I read somewhere that join() is the flatMap of Completable future, so I think I could use this method to do something like aFuture.thenCombine(bFuture, ((Function<CompletableFuture<C>,C>) CompletableFuture::join).compose(this::makeSomeC) but I'm not sure this is the proper/advised way to go. And I cannot say that this help readability in any way...
To me it looks like thenCompose is the direct equivalent of the Haskell Monad.bind.
thenCompose can be nested in the same way as Haskell monad bind, which is also the result of a do-expression in Haskell. Using that your problem can be solved like this:
public CompletableFuture<C> doStuff() {
CompletableFuture<A> aFuture = makeSomeA();
CompletableFuture<B> bFuture = makeSomeB();
return aFuture.thenCompose(a -> bFuture.thenCompose(b -> makeSomeC(a, b)));
}
Explanation of the types
This can be seen by inspecting the types of the functions.
Monad bind -- which is written >>= in Haskell -- has the following type:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
thenCompose in Java has the following signature:
public <U> CompletionStage<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn)
The above converted to Haskell syntax, with an extra parameter as an explicit this, looks like this:
thenCompose :: CompletionStage T -> (T -> CompletionStage U) -> CompletionStage U
We can see that this has the same structure as the Haskell type. The difference is the names, and the fact Haskell's support for higher-kinded types is not exactly expressed by Java interfaces.
Note on the Haskell code in the question
But I am a bit puzzled by your Haskell code. To me it looks like your Haskell code is doing the following:
public CompletableFuture<C> doStuff() {
return makeSomeA().thenCompose(a -> makeSomeB().thenCompose(b -> makeSomeC(a, b)));
}
That is, waiting until the makeSomeA operation has completed before starting on makeSomeB. The Java code on the other hand starts the two operations in parallel, then waits for the result before starting on C. But maybe it is a laziness thing.
I guess the simplest solution is just to apply a thenCompose(identity()) afterwards:
public CompletableFuture<C> doStuff() {
CompletableFuture<A> aFuture = makeSomeA();
CompletableFuture<B> bFuture = makeSomeB();
CompletableFuture<CompletableFuture<C>> cFuture = aFuture.thenCombine(bFuture, this::makeSomeC);
return cFuture.thenCompose(Function.identity());
}
Alternatively, introduce a simple Pair class to combine the results of A and B and use thenCompose():
public CompletableFuture<C> doStuff() {
CompletableFuture<A> aFuture = makeSomeA();
CompletableFuture<B> bFuture = makeSomeB();
CompletableFuture<Pair<A, B>> cFuture = aFuture.thenCombine(bFuture, Pair::new);
return cFuture.thenCompose(p -> makeSomeC(p.a, p.b));
}
private static class Pair<A, B> {
A a;
B b;
public Pair(A a, B b) {
this.a = a;
this.b = b;
}
}
And a third alternative without Pair:
public CompletableFuture<C> doStuff() {
CompletableFuture<A> aFuture = makeSomeA();
CompletableFuture<B> bFuture = makeSomeB();
CompletableFuture<Void> cFuture = CompletableFuture.allOf(aFuture, bFuture);
return cFuture.thenCompose(__ -> makeSomeC(aFuture.join(), bFuture.join()));
}

Why Java's Optional doesn't call Consumer in ifPresent()?

public class TestSupplier {
Optional<Integer> opt1;
public static void main(String[] args) {
// TODO Auto-generated method stub
TestSupplier ts1 = new TestSupplier();
ts1.opt1 = ts1.average(100,20,30,80);
Consumer<Integer> cns1 = (x) -> x += 3;
ts1.opt1.ifPresent(cns1);
System.out.println(ts1.opt1.get());
}
private Optional<Integer> average(int... n1) {
if (n1.length == 0) return Optional.empty();
int sum = 0;
for(int score: n1) sum += score;
return Optional.of(sum/n1.length);
}
}
when I run the code the result is 57 (that is the correct result of 100, 20, 30, 80 average) but I create a Consumer that should increment the result by 3... but it seems to not work.
Can someone help me?
The Consumer action is actually being run but the body you provided modifies only a local instance which eventually gets lost. The ifPresent() method should be used for performing side-effects(actions) only.
If you want to perform a calculation on a value held by an Optional instance, use map() instead.
ts1.opt1
.map(x -> x + 3).orElseThrow(...)
Remember to be careful when using get() on an Optional instance. Before you decide to use it, have a look at orElse, orElseGet, and orElseThrow.
Consumer<Integer> cns1 = new Consumer<Integer>() {
public #Override void accept(Integer x) {
// x is a local variable
x += 3; // unboxing, adding, boxing
// the local variable has been changed
}
};
It is that case when turning a lambda into an anonymous class perfectly makes this all clear to understand.
The best possible way here is
ts1.opt1.map(x -> x + 3).ifPresent(System.out::println);
You could use an instance of a mutable class (e.g. the AtomicInteger class):
Consumer<AtomicInteger> cns1 = x -> x.addAndGet(3);
which changes its state after accepting the Consumer<AtomicInteger> (although it is not recommended, look at #pivovarit's answer).
Furthermore, the line
IntStream.of(100, 20, 30, 80).average().ifPresent(System.out::println);
might replace all your routine work.

Collect arguments to apply to curried functions in Java/Scala

I would like to create a class in Java 8 which is able to recursively create an object which has a method that takes a function parameter based on the parameters I added.
For example, I would like to be able to do this:
new X().param(23).param("some String").param(someObject)
.apply((Integer a) -> (String b) -> (Object c) -> f(a,b,c))
The apply method would then apply the collected parameters to the given function.
I feel this should be possible without reflection while maintaing type-safety, but I can't quite figure out how. A solution in Scala is also welcome, if I can translate it to Java 8. If it's not possible, I'll also accept an answer that explains why.
What I have so far is essentially this:
class ParamCmd<A,X> {
final A param;
public ParamCmd(A param) {
this.param = param;
}
public<B> ParamCmd<B, Function<A,X>> param(B b) {
return new ParamCmd<>(b);
}
public void apply(Function<A,X> f) {
// this part is unclear to me
}
public static void main(String[] args) {
new ParamCmd<Integer,String>(0).param("oops").param(new Object())
// the constructed function parameters are reversed relative to declaration
.apply((Object c) -> (String b) -> (Integer a) ->
"args were " + a + " " + b + " " + c
);
}
}
As noted in the code comments, my problems are keeping the function parameters in the order of the calls of param(), and actually applying the parameters.
For an unlimited amount of parameters, the only solution I could think of is with Heterogeneous Lists in Scala.
It is probably isn't feasible in Java as there is type level computation going on with path-dependant types.
Using Heterogeneous Lists and Path-Dependant types:
import scala.language.higherKinds
object Main extends App {
val builder1 = HCons(23, HCons("Hello", HNil))
val builder2 = HCons(42L, builder1)
val res1:String = builder1.apply(i => s => i + s)
val res2:String = builder2.apply(l => i => s => (i+l) + s)
println(res1) // 23Hello
println(res2) // 65Hello
}
sealed trait HList {
type F[Res]
def apply[Res]: F[Res] => Res
}
case class HCons[Head, HTail <: HList](head: Head, tail: HTail) extends HList {
type F[Res] = Head => (tail.type)#F[Res]
def apply[Res]: F[Res] => Res = f => tail.apply(f(head))
}
case object HNil extends HList {
type F[Res] = Res
def apply[Res]: F[Res] => Res = identity
}
This code prints:
23Hello
65Hello
The second, more limited way of doing this, but which might work with Java, is to create multiple classes for each function length, which returns the next sized function length class wrapping the value, up to some maximal length - See the Applicative Builder in Scalaz: "Scalaz Applicative Builder"
This doesn't answer your question. However, maybe it helps someone to find a solution, or to explain why it isn't possible in Java and/or Scala.
It can be done in C++, with an arbitrary number of parameters, and without losing type-safety. The call-side look as follows. Unfortunately, the lambda syntax in C++ is quite verbose.
bar{}.param(23).param("some String").param(4.2).apply(
[](int i) {
return [=](std::string s) {
return [=](double d) {
std::cout << i << ' ' << s << ' ' << d << '\n';
};
};
});
Following is the definition of foo and bar. The implementation is straight-forward. However, I doubt that it is possible to build something like this in Java, because the way type parameters work in Java. Generics in Java can only be used to avoid type casts, and that's not enough for this use case.
template <typename Param, typename Tail>
struct foo {
Param _param;
Tail _tail;
template <typename P>
auto param(P p) {
return foo<P, foo>{p, *this};
}
template <typename Function>
auto apply(Function function) {
return _tail.apply(function)(_param);
}
};
struct bar {
template <typename P>
auto param(P p) {
return foo<P, bar>{p, *this};
}
template <typename Function>
auto apply(Function function) {
return function;
}
};
Sorry I just could give some leads in Scala:
Perhaps it would help to have a look at http://www.scala-lang.org/api/2.10.4/index.html#scala.Function$
.apply((Integer a) -> (String b) -> (Object c) -> f(a,b,c))
pretty much looks like Function.uncurried
param(23).param("some String").param(someObject)
could be implemented using a list for an accumulator if you don't care for Type safety. If you want to keep the Types you could use the HList out of Shapeless https://github.com/milessabin/shapeless which comes with a handy tuppled method.
Implementation of param():
import shapeless._
import HList._
import syntax.std.traversable._
class Method(val l : HList = HNil) {
def param(p: Any) = new Method( p :: l )
}
Example
scala> val m = new Method().param(1).param("test")
m: Method = Method#1130ad00
scala> m.l
res8: shapeless.HList = test :: 1 :: HNil

Categories