• Post Reply Bookmark Topic Watch Topic
  • New Topic

What can I do with the new Features in Java 8 and what not?

 
Pierrot Mongonnam
Greenhorn
Posts: 14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi together,

one of the new features of Java 8 is the internal iteration (eg. foreach() method versus for loop). My question how can I implement my following function with an internal iteration?



To summarize: I pass a list of Integers to my function and I print them out in a block of lines with 6 integers respectively,separated with a comma. After the last number no comma will be printed.

My question: How can I implement it with an internal iteration e.g. with a forEach()?

Thanks for helping!
 
Stephan van Hulst
Bartender
Posts: 6583
84
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You can't, unless you use an object to hold the counter. You see, lambda's are not allowed to update variables declared outside of their scope.
 
Pierrot Mongonnam
Greenhorn
Posts: 14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Stephan van Hulst. You are right. I've tried like the following ( my trials in comments) and I quickly realized that it cannot work

 
Pierre-Yves Saumont
Author
Ranch Hand
Posts: 94
17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If the requirement is to use forEach, I would do this:

 
Pierre-Yves Saumont
Author
Ranch Hand
Posts: 94
17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
But if you simply want to use "internal iteration", the right way to do it is:

 
Pierre-Yves Saumont
Author
Ranch Hand
Posts: 94
17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you insist on using forEach and still want to be functional (no side effect), I would propose:



Or better, you may use a generic version of the toDelimitedString method:


 
Pierrot Mongonnam
Greenhorn
Posts: 14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Dear Pierre-Yves Saumont, it's an honor to get an answer from you personally. Many thanks for your detailled answers. For sure many of your solutions were known by me. But the main requirement was to print the integers line by line with  a new line after 6 integers, comma separated. The Idea was as following: I though the new Java 8 Paradigm should completely replace the formal techniques like external iterations. So I brougth this example with an external iteration and was about trying to implement it with an internal iteration and I saw the limitation of the internal iteration. This is what I tried to summarize in my question in the subject: Can I always replace an external iteration with an internal ,while iterating on a collection for example?
 
Pierre-Yves Saumont
Author
Ranch Hand
Posts: 94
17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I am really sorry for not having read the requirements correctly.

What you need may be achieved with a specific collector:



I do not say that this is the best way to do it in Java. It is however one possible way, using the "Java 8 paradigm".
 
Pierrot Mongonnam
Greenhorn
Posts: 14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Merci Mr. Saumont !!!. This is an answer to my question! Many thanks!! So we can conclude the new Java 8 Paradigm (functional programming, lambdas, etc) will coexist with the formal techniques (anonymous classes, external iterations, etc)
 
Pierre-Yves Saumont
Author
Ranch Hand
Posts: 94
17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You may of course push abstraction a bit further by storing the number of elements in the Collector. This way, you will provide the number (6) when creating the collector, and you may reuse the collector class with a different number of elements.

You may also replace the identity finisher with a function changing a list of A into a delimited String. Or better, you may pass in this function when calling the collector constructor.

So, although using collectors may seem a bit more complicated than the imperative way, it is much more powerful!
 
Stephan van Hulst
Bartender
Posts: 6583
84
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The solution can be simplified a little bit more by realizing that the accumulation type used is a List<List<T>>, and wrapping that in a custom Accumulation class. Instead of extending Collector, we can then just use the Collector.of() method. Since this collector does not produce a correct result for parallel streams, we can simply let the combiner function throw an UnsupportedOperationException.

Along with Pierre-Yves' suggestions to store the max number of elements in the collector and to provide an additional downstream collector, this yields the following code:

Because we have a downstream collector, the Accumulation no longer wraps a List<List<T>>, but instead a List<R>. The downstream collector is responsible for transforming a sub-sequence of Ts to an R.

[edit]

Pierre-Yves, your great solutions always trigger me to have an afternoon of fun with streams. Please have a cow.
 
Pierre-Yves Saumont
Author
Ranch Hand
Posts: 94
17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you Stephan! I really appreciate this kind of discussion.
 
Will Myers
Ranch Hand
Posts: 395
Java jQuery Scala
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Wow! That's a lot of code to replace the original 20 lines...
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!