Skip to main content
Code Review

Return to Answer

replaced http://codereview.stackexchange.com/ with https://codereview.stackexchange.com/
Source Link

One should emphasize that the perceived readability largely depends on how familiar the reader is with certain concepts. Most programmers know the good, old for loop that has basically been present since the time when programs have been delivered as punched cards. In contrast to that, someone who has been programming Lisp or Haskell in the past 20 years may consider even the most complex Java lambda as a "toy example".

The advantage of easier parallelizability of the lambdas has already been pointed out in the other answer. But the actual crux is the transition from external iteration to internal iteration: Leaving the decision of how to iterate a set of elements to the container implementation offers new degrees of freedom for various sorts of optimization (search for "Pipelined Execution", for example, in this tutorial).


This leads to your actual question. The example is a bit contrived, and may be too simple to really see the benefits of using stream operations with lambdas. This is also why the iterative version with the for loop is certainly appropriate here. What remains open is the question about how to keep things readable for the cases where lambdas are more appropriate.

The fluid version

// #2 fluid lambdas
existing.stream()
 .filter(item -> !updated.contains(item))
 .forEach(item -> System.out.println("item " + item + " removed"));

is the intended and most idiomatic way to write this. However, for more complex lambda expressions, I think there's nothing wrong with giving names to lambdas, probably in the form of local variables or static helper methods.

This might seem like a step towards the "awful looking middle ground" that you sketched. But in this case, it is only looking awful due to the code bloat that is caused here: You have to specify the types of the lambdas, and in fact, the type declaration causes more code than the actual lambda itself. So you should probably not extract a lambda like

Predicate<String> onlyRemovedItems = item -> !updated.contains(item);

But if the condition was more complicated, it could be beneficial: Imagine that you wanted to use such a more complex lambda as a "building block" at several places, in various other stream operations. Of course, you always could "inline" the whole lambda into one large, deeply nested lambda that solely resides at the call site. But this hinders readability, and extracting it would allow you to use it conveniently, probably via method references.

(An extreme example where I implemented two versions - once "inlined", and once with dedicated, easily readable names - can be seen in http://codereview.stackexchange.com/a/79082/41175 https://codereview.stackexchange.com/a/79082/41175 )

One should emphasize that the perceived readability largely depends on how familiar the reader is with certain concepts. Most programmers know the good, old for loop that has basically been present since the time when programs have been delivered as punched cards. In contrast to that, someone who has been programming Lisp or Haskell in the past 20 years may consider even the most complex Java lambda as a "toy example".

The advantage of easier parallelizability of the lambdas has already been pointed out in the other answer. But the actual crux is the transition from external iteration to internal iteration: Leaving the decision of how to iterate a set of elements to the container implementation offers new degrees of freedom for various sorts of optimization (search for "Pipelined Execution", for example, in this tutorial).


This leads to your actual question. The example is a bit contrived, and may be too simple to really see the benefits of using stream operations with lambdas. This is also why the iterative version with the for loop is certainly appropriate here. What remains open is the question about how to keep things readable for the cases where lambdas are more appropriate.

The fluid version

// #2 fluid lambdas
existing.stream()
 .filter(item -> !updated.contains(item))
 .forEach(item -> System.out.println("item " + item + " removed"));

is the intended and most idiomatic way to write this. However, for more complex lambda expressions, I think there's nothing wrong with giving names to lambdas, probably in the form of local variables or static helper methods.

This might seem like a step towards the "awful looking middle ground" that you sketched. But in this case, it is only looking awful due to the code bloat that is caused here: You have to specify the types of the lambdas, and in fact, the type declaration causes more code than the actual lambda itself. So you should probably not extract a lambda like

Predicate<String> onlyRemovedItems = item -> !updated.contains(item);

But if the condition was more complicated, it could be beneficial: Imagine that you wanted to use such a more complex lambda as a "building block" at several places, in various other stream operations. Of course, you always could "inline" the whole lambda into one large, deeply nested lambda that solely resides at the call site. But this hinders readability, and extracting it would allow you to use it conveniently, probably via method references.

(An extreme example where I implemented two versions - once "inlined", and once with dedicated, easily readable names - can be seen in http://codereview.stackexchange.com/a/79082/41175 )

One should emphasize that the perceived readability largely depends on how familiar the reader is with certain concepts. Most programmers know the good, old for loop that has basically been present since the time when programs have been delivered as punched cards. In contrast to that, someone who has been programming Lisp or Haskell in the past 20 years may consider even the most complex Java lambda as a "toy example".

The advantage of easier parallelizability of the lambdas has already been pointed out in the other answer. But the actual crux is the transition from external iteration to internal iteration: Leaving the decision of how to iterate a set of elements to the container implementation offers new degrees of freedom for various sorts of optimization (search for "Pipelined Execution", for example, in this tutorial).


This leads to your actual question. The example is a bit contrived, and may be too simple to really see the benefits of using stream operations with lambdas. This is also why the iterative version with the for loop is certainly appropriate here. What remains open is the question about how to keep things readable for the cases where lambdas are more appropriate.

The fluid version

// #2 fluid lambdas
existing.stream()
 .filter(item -> !updated.contains(item))
 .forEach(item -> System.out.println("item " + item + " removed"));

is the intended and most idiomatic way to write this. However, for more complex lambda expressions, I think there's nothing wrong with giving names to lambdas, probably in the form of local variables or static helper methods.

This might seem like a step towards the "awful looking middle ground" that you sketched. But in this case, it is only looking awful due to the code bloat that is caused here: You have to specify the types of the lambdas, and in fact, the type declaration causes more code than the actual lambda itself. So you should probably not extract a lambda like

Predicate<String> onlyRemovedItems = item -> !updated.contains(item);

But if the condition was more complicated, it could be beneficial: Imagine that you wanted to use such a more complex lambda as a "building block" at several places, in various other stream operations. Of course, you always could "inline" the whole lambda into one large, deeply nested lambda that solely resides at the call site. But this hinders readability, and extracting it would allow you to use it conveniently, probably via method references.

(An extreme example where I implemented two versions - once "inlined", and once with dedicated, easily readable names - can be seen in https://codereview.stackexchange.com/a/79082/41175 )

I wrote "lamda" instead of "lambda" 4 times - since this a core term, correcting the spelling is hopefully justified...
Source Link
Marco13
  • 831
  • 4
  • 8

One should emphasize that the perceived readability largely depends on how familiar the reader is with certain concepts. Most programmers know the good, old for loop that has basically been present since the time when programs have been delivered as punched cards. In contrast to that, someone who has been programming Lisp or Haskell in the past 20 years may consider even the most complex Java lambda as a "toy example".

The advantage of easier parallelizability of the lambdas has already been pointed out in the other answer. But the actual crux is the transition from external iteration to internal iteration: Leaving the decision of how to iterate a set of elements to the container implementation offers new degrees of freedom for various sorts of optimization (search for "Pipelined Execution", for example, in this tutorial).


This leads to your actual question. The example is a bit contrived, and may be too simple to really see the benefits of using stream operations with lambdas. This is also why the iterative version with the for loop is certainly appropriate here. What remains open is the question about how to keep things readable for the cases where lamdaslambdas are more appropriate.

The fluid version

// #2 fluid lambdas
existing.stream()
 .filter(item -> !updated.contains(item))
 .forEach(item -> System.out.println("item " + item + " removed"));

is the intended and most idiomatic way to write this. However, for more complex lambda expressions, I think there's nothing wrong with giving names to lambdas, probably in the form of local variables or static helper methods.

This might seem like a step towards the "awful looking middle ground" that you sketched. But in this case, it is only looking awful due to the code bloat that is caused here: You have to specify the types of the lamdaslambdas, and in fact, the type declaration causes more code than the actual lamdalambda itself. So you should probably not extract a lambda like

Predicate<String> onlyRemovedItems = item -> !updated.contains(item);

But if the condition was more complicated, it could be beneficial: Imagine that you wanted to use such a more complex lamdalambda as a "building block" at several places, in various other stream operations. Of course, you always could "inline" the whole lambda into one large, deeply nested lambda that solely resides at the call site. But this hinders readability, and extracting it would allow you to use it conveniently, probably via method references.

(An extreme example where I implemented two versions - once "inlined", and once with dedicated, easily readable names - can be seen in http://codereview.stackexchange.com/a/79082/41175 )

One should emphasize that the perceived readability largely depends on how familiar the reader is with certain concepts. Most programmers know the good, old for loop that has basically been present since the time when programs have been delivered as punched cards. In contrast to that, someone who has been programming Lisp or Haskell in the past 20 years may consider even the most complex Java lambda as a "toy example".

The advantage of easier parallelizability of the lambdas has already been pointed out in the other answer. But the actual crux is the transition from external iteration to internal iteration: Leaving the decision of how to iterate a set of elements to the container implementation offers new degrees of freedom for various sorts of optimization (search for "Pipelined Execution", for example, in this tutorial).


This leads to your actual question. The example is a bit contrived, and may be too simple to really see the benefits of using stream operations with lambdas. This is also why the iterative version with the for loop is certainly appropriate here. What remains open is the question about how to keep things readable for the cases where lamdas are more appropriate.

The fluid version

// #2 fluid lambdas
existing.stream()
 .filter(item -> !updated.contains(item))
 .forEach(item -> System.out.println("item " + item + " removed"));

is the intended and most idiomatic way to write this. However, for more complex lambda expressions, I think there's nothing wrong with giving names to lambdas, probably in the form of local variables or static helper methods.

This might seem like a step towards the "awful looking middle ground" that you sketched. But in this case, it is only looking awful due to the code bloat that is caused here: You have to specify the types of the lamdas, and in fact, the type declaration causes more code than the actual lamda itself. So you should probably not extract a lambda like

Predicate<String> onlyRemovedItems = item -> !updated.contains(item);

But if the condition was more complicated, it could be beneficial: Imagine that you wanted to use such a more complex lamda as a "building block" at several places, in various other stream operations. Of course, you always could "inline" the whole lambda into one large, deeply nested lambda that solely resides at the call site. But this hinders readability, and extracting it would allow you to use it conveniently, probably via method references.

(An extreme example where I implemented two versions - once "inlined", and once with dedicated, easily readable names - can be seen in http://codereview.stackexchange.com/a/79082/41175 )

One should emphasize that the perceived readability largely depends on how familiar the reader is with certain concepts. Most programmers know the good, old for loop that has basically been present since the time when programs have been delivered as punched cards. In contrast to that, someone who has been programming Lisp or Haskell in the past 20 years may consider even the most complex Java lambda as a "toy example".

The advantage of easier parallelizability of the lambdas has already been pointed out in the other answer. But the actual crux is the transition from external iteration to internal iteration: Leaving the decision of how to iterate a set of elements to the container implementation offers new degrees of freedom for various sorts of optimization (search for "Pipelined Execution", for example, in this tutorial).


This leads to your actual question. The example is a bit contrived, and may be too simple to really see the benefits of using stream operations with lambdas. This is also why the iterative version with the for loop is certainly appropriate here. What remains open is the question about how to keep things readable for the cases where lambdas are more appropriate.

The fluid version

// #2 fluid lambdas
existing.stream()
 .filter(item -> !updated.contains(item))
 .forEach(item -> System.out.println("item " + item + " removed"));

is the intended and most idiomatic way to write this. However, for more complex lambda expressions, I think there's nothing wrong with giving names to lambdas, probably in the form of local variables or static helper methods.

This might seem like a step towards the "awful looking middle ground" that you sketched. But in this case, it is only looking awful due to the code bloat that is caused here: You have to specify the types of the lambdas, and in fact, the type declaration causes more code than the actual lambda itself. So you should probably not extract a lambda like

Predicate<String> onlyRemovedItems = item -> !updated.contains(item);

But if the condition was more complicated, it could be beneficial: Imagine that you wanted to use such a more complex lambda as a "building block" at several places, in various other stream operations. Of course, you always could "inline" the whole lambda into one large, deeply nested lambda that solely resides at the call site. But this hinders readability, and extracting it would allow you to use it conveniently, probably via method references.

(An extreme example where I implemented two versions - once "inlined", and once with dedicated, easily readable names - can be seen in http://codereview.stackexchange.com/a/79082/41175 )

Source Link
Marco13
  • 831
  • 4
  • 8

One should emphasize that the perceived readability largely depends on how familiar the reader is with certain concepts. Most programmers know the good, old for loop that has basically been present since the time when programs have been delivered as punched cards. In contrast to that, someone who has been programming Lisp or Haskell in the past 20 years may consider even the most complex Java lambda as a "toy example".

The advantage of easier parallelizability of the lambdas has already been pointed out in the other answer. But the actual crux is the transition from external iteration to internal iteration: Leaving the decision of how to iterate a set of elements to the container implementation offers new degrees of freedom for various sorts of optimization (search for "Pipelined Execution", for example, in this tutorial).


This leads to your actual question. The example is a bit contrived, and may be too simple to really see the benefits of using stream operations with lambdas. This is also why the iterative version with the for loop is certainly appropriate here. What remains open is the question about how to keep things readable for the cases where lamdas are more appropriate.

The fluid version

// #2 fluid lambdas
existing.stream()
 .filter(item -> !updated.contains(item))
 .forEach(item -> System.out.println("item " + item + " removed"));

is the intended and most idiomatic way to write this. However, for more complex lambda expressions, I think there's nothing wrong with giving names to lambdas, probably in the form of local variables or static helper methods.

This might seem like a step towards the "awful looking middle ground" that you sketched. But in this case, it is only looking awful due to the code bloat that is caused here: You have to specify the types of the lamdas, and in fact, the type declaration causes more code than the actual lamda itself. So you should probably not extract a lambda like

Predicate<String> onlyRemovedItems = item -> !updated.contains(item);

But if the condition was more complicated, it could be beneficial: Imagine that you wanted to use such a more complex lamda as a "building block" at several places, in various other stream operations. Of course, you always could "inline" the whole lambda into one large, deeply nested lambda that solely resides at the call site. But this hinders readability, and extracting it would allow you to use it conveniently, probably via method references.

(An extreme example where I implemented two versions - once "inlined", and once with dedicated, easily readable names - can be seen in http://codereview.stackexchange.com/a/79082/41175 )

lang-java

AltStyle によって変換されたページ (->オリジナル) /