• Post Reply Bookmark Topic Watch Topic
  • New Topic

how to avoid a loop in repeated replaces  RSS feed

 
Jeanne Boyarsky
author & internet detective
Marshal
Posts: 37181
515
Eclipse IDE Java VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I;m trying to write code that does that following as a map() step in a stream pipeline. In other words, it goes through a bunch of strings and removes certain sequences of letters form each. This works, but I don't like the loop. Is there anything I can do to be more functional here?



And yes, I'm aware this code needs a refactoring for performance so it doesn't read the file multiple times.
 
Pierre-Yves Saumont
Author
Ranch Hand
Posts: 103
17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Jeanne,

Here is a functional solution. Note that this is using only Java standard library classes, which considerably limit possibilities. The most important problem is about Optional which doesn't carry the error in case data is missing. In my book (Functional Programming in Java), I show how to implement much more powerful data structures. Also note that the removeForCustomLogic is in curried form, but you can use a BiFunction if you prefer. I have included a main method to show how it is intended to be used. Of course, using the Java HashSet this way is not functional at all, but it is supposed to be replaced by a call to the getPrefixes method.



I plan to write a chapter in my book about translating imperative programs into functional style. May I use your example?

Pierre-Yves
 
Stephan van Hulst
Saloon Keeper
Posts: 7743
142
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think you can use a sequential reduction, although it technically breaks the contract of reduce(), which requires an associative operator.

Please note that without the call to sequential(), there is a high chance of failure because the reduction is not associative. That is, ((s-p1)-p2) has a different result than (s-(p1-p2)).

Why not write a custom UnaryOperator? I would just keep this code procedural, it's much easier to read, and it guarantees that the operation is performed sequentially. Also, functional code doesn't play nice with I/O. I don't recommend combining the two.
 
Stephan van Hulst
Saloon Keeper
Posts: 7743
142
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think this problem is a fantastic example why maybe it was a mistake to intertwine parallelization and Streams so much. The rationale is that solving a problem in parallel or sequentially should be an implementation detail, hidden by our beautiful higher order functions:
java.util.stream wrote:Except for operations identified as explicitly nondeterministic, such as findAny(), whether a stream executes sequentially or in parallel should not change the result of the computation.

The problem is that this implementation detail leaves methods like reduce() theoretically useless in a lot of cases if they don't make guarantees on the order of reduction. Either the API should have made hard guarantees for sequential streams, or they should have added a method such as reduceLeft() or foldLeft().
 
Pierre-Yves Saumont
Author
Ranch Hand
Posts: 103
17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
prefixes.stream().sequential().reduce(s,...


I don't think you need to call sequential because stream() returns a sequential stream. But of course, this is a dangerous trick. I you later forget about it and make the stream parallel, It might give a totally unexpected result.

Beside this, I agree that Java 8 streams are mostly useless for functional programming! The same is true about Optional, since it can only represent data for which absence is not an error. Here is how the same example looks like using the library developed in my book:



Of course, any functional library may be used instead.


 
Jeanne Boyarsky
author & internet detective
Marshal
Posts: 37181
515
Eclipse IDE Java VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ooh!. Thanks guys!

Pierre-Yves: yes you can use this example. It comes from a data migration thing I'm doing for this site. It doesn't belong to my employer.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!