El método Stream.reduce toma un BinaryOperator como argumento. La firma de función de un BinaryOperator es (T,T) -> T . El método BigDecimal::min tiene solo 1 parámetro en su firma de método (es decir, (T) -> T ).
¿Por qué el compilador no se queja cuando paso BigDecimal::min al método Stream.reduce ?
Código de muestra:
List<BigDecimal> bigDecimalList = new ArrayList<>(); bigDecimalList.add(BigDecimal.valueOf(1)); bigDecimalList.add(BigDecimal.valueOf(2)); bigDecimalList.add(BigDecimal.valueOf(3)); BigDecimal minResult = bigDecimalList.stream().reduce(BigDecimal::min).orElse(BigDecimal.ZERO);Gracias.
Esto en realidad se llama Referencia a un método de instancia de un objeto arbitrario de un tipo particular .
El compilador toma la instancia de llamada como primer argumento y, como tal, estos son equivalentes:
BinaryOperator<BigDecimal> b = (left, right) -> left.min(right); BinaryOperator<BigDecimal> b2 = BigDecimal::min; b2.apply(left, right);Las cosas son mucho más divertidas en mi opinión cuando tienes algo como esto:
@FunctionalInterface interface TriFunction<A, B, C, R> { R apply(A a, B b, C c); }y una clase teórica:
class Test { int x; int y; public Test(int x, int y) { this.x = x; this.y = y; } public Test copy(int n, int m) { return new Test(m, n); } }Entonces podrías escribir algo como esto:
TriFunction<Test, Integer, Integer, Test> f = Test::copy; TriFunction<Test, Integer, Integer, Test> f2 = (test, i, j) -> test.copy(i, j);Porque BigDecimal::min es un método de instancia. Javac es lo suficientemente inteligente como para convertirlo en (T, T) -> T si usa BigDecimal::min . El primer parámetro pasado al BinaryOperator resultante será la instancia y el segundo será el parámetro de min (aunque en el caso de BinaryOperator se requiere que el orden se pueda invertir). Será (T) -> T si usa algo como new BigInteger(1)::min .