lambdaj doesn't really offer lambda expressions
This is correct.
[lambdaj] provides some of the same functionality such as closures
If by this you mean "it provides closures"—no, it doesn't. A closure cannot exist without a lambda expression; it is actually a special case of a lambda expression, one which is the most demanding to implement.
Unfortunately, LambdaJ's project documentation is quite misleading in applying the term "closure" to something which doesn't qualify. An example from its Closures wiki page:
Closure println = closure(); { of(System.out).println(var(String.class)); }
The example is followed by this explanation:
In particular the var()
method binds a free variable of type String
to the closure.
That statement is simply false: there is no variable binding at all happening there, let alone a free variable. The construct results in something resembling a unary function, which expects a String
argument. (Well, what it actually expects is an Object
, but will fail at runtime if passed a non-String
.)
On the other hand, the of()
call in the example does go a bit in the direction of local variable capture. We might say that the argument passed to of()
is captured by the object which it returns. However, we cannot refer to it in any further syntax; it is just the implicit target of the method call that follows. This is a far cry from full closures.
I'm wondering what 1.8's lambda expressions can bring to a Java project that lambdaj can't. Is it just a matter of increased performance with native support for anonymous functions?
Since LambdaJ doesn't provide the ability to write anonymous functions, the question is technically unanswerable. However, rest assured that Java 8's closures will outperform LambdaJ on a usecase-by-usecase basis because LambdaJ is fundamentally based on reflection, whereas Java's closures don't need it at all.
Will expressions similar to lambdaj's collection manipulation functions be present in 1.8?
Absolutely, and the support is very serious and complete. There are both more features, and the features are more composable. LamdaJ's capabilities are dwarfed by what is available out-of-the-box in Java 8. Check out the Streams API.
One of the primary design goals behind the Streams API was never even meant to be implemented by LambdaJ: the automatic parallelization of processing. Sure, FP-oriented collection processing looks nicer than the imperative idiom, but this is about much more than looks: it is a fundamental change. It is Java's bet on the future of computing, where the only way to boost performance will be to involve more parallel streams of processing.