Given:
import com.google.common.collect.ImmutableMap;
import java.util.function.Function;
import java.util.stream.Collector;
import java.util.stream.Stream;
The target type of a lambda expression is determined entirely from context, as discussed in the Java tutorial. Therefore, lambdas do not contribute to type parameter inference; instead, they rely on it. Method references "are compact, easy-to-read lambda expressions for methods that already have a name" (Oracle Java Tutorial; emphasis added), so the there is no distinction there that would color type analysis differently when they are involved.
When you assign your lambda / method reference to a variable, that variable's type provides the context for inferring type parameters. When you pass them directly to a generic method, however, you need some other mechanism to infer their types. In some cases, other arguments to the method might serve that purpose. In your particular case, it looks like you probably need explicit type arguments:
ImmutableMap map2 = Stream.of("1", "2", "3").collect(
Testcase.toImmutableMap(i -> i, Integer::valueOf).build());
Update
With respect to the updated question, it looks like Java can infer types correctly in the map3 case in part because the determination is not complicated by invocation of the MapCollectorBuilder.build() method. Without build(), the type of map3 provides the context to determine the first type argument of Stream.collect(), which gives both K and V. Type parameter T can be inferred from the (inferred) type of the Stream.
With build() involved, however, I think Java is separating the question of inferring the type parameters for generic method toImmutableMap() from the question of the type of the return value of invoking build() on its return value. In other words, it wants determine the type of the object returned by toImmutableMap() before it considers the type of the value obtained by invoking a method on that value.