A simple vista, Java y C# parecen ofrecer lo mismo:
users.stream()
.filter(u -> u.getAge() > 50)
.toList();
users.Where(u => u.Age > 50).ToList();
- Sintaxis similar
- Misma intención
Pero internamente… son dos mundos completamente distintos.
- En Java, una lambda es código ejecutable
- En LINQ, puede ser datos (un AST)
Y eso cambia todo.
En Java, esto:
Predicate<User> p = u -> u.getAge() > 50;
Se compila a bytecode usando invokedynamic
Es equivalente a:
class Lambda implements Predicate<User> {
public boolean test(User u) {
return u.getAge() > 50;
}
}
No hay forma de saber:
- qué propiedad se accede (age)
- qué operador se usa (>)
- qué constante (50)
Solo podés ejecutarla, no analizarla
Por lo tanto, siempre ocurre en memoria. Nunca puede transformarse en sql o en nada
En .NET LINQ, esto:
users.Where(u => u.Age > 50)
Puede ser interpretado como:
Expression<Func<User, bool>>
Esto NO es una función
Es un árbol de expresión (AST)
¿Cómo se ve ese AST?
Conceptualmente:
GreaterThan
├── MemberAccess (Age)
└── Constant (50)
O en código:
BinaryExpression(
left: MemberExpression("Age"),
operator: GreaterThan,
right: Constant(50)
)
Ahora sí podés:
- traducir a SQL
- optimizar
- serializar
- ejecutar en distintos motores
¿Por qué Java eligió este camino?
Java priorizó:
- simplicidad
- performance
- compatibilidad
Las lambdas fueron diseñadas como: “syntactic sugar” sobre interfaces funcionales
No como estructuras analizables.
¿Se podría implementar LINQ en Java?
Sí… pero requeriría:
- lambdas introspectables
- un AST estándar en el lenguaje
- cambios en el compilador
Streams y LINQ no son equivalentes.
- Streams son pipelines de ejecución
- LINQ es un lenguaje de queries embebido

No hay comentarios.:
Publicar un comentario