This week's book giveaway is in the HTML Pages with CSS and JavaScript forum.
We're giving away four copies of React Cookbook: Recipes for Mastering the React Framework and have David Griffiths & Dawn Griffiths on-line!
See this thread for details.
Win a copy of React Cookbook: Recipes for Mastering the React Framework this week in the HTML Pages with CSS and JavaScript forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Ron McLeod
  • Paul Clapham
  • Rob Spoor
  • Liutauras Vilda
Sheriffs:
  • Jeanne Boyarsky
  • Junilu Lacar
  • Tim Cooke
Saloon Keepers:
  • Tim Holloway
  • Piet Souris
  • Stephan van Hulst
  • Tim Moores
  • Carey Brown
Bartenders:
  • Frits Walraven
  • Himai Minh

Am I Just Streams Happy? Is this decent code?

 
Bartender
Posts: 1035
31
Eclipse IDE Postgres Database C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
So, interview problem, which I might have blown, standard question, they wanted to watch me code, let me pick Java.

Given two Strings, have your function return whether or not they are Anagrams.

I've done this before in several different languages, not within the last year probably, but within the last three.

I can think of three solutions off the top of my head.
In all three cases, quick exit at the top with false if the Strings aren't of equal length, because then it is hopeless.
1. Turn each String into a char array

Then either sort each char array in place, O(n*log(n)) compare, O(n)  ==> O(n*log(n)), space(n)

I could have got that working in time, it is straightforward and old hat, but noooo....

I may have thrown myself out of the game right there, for not doing that...I remember actually doing TreeMaps of count by characters, and even now can't remember if there was a real advantage to that or it was because the problem required you to so you could show you figured out TreeMap.  I vaguely remember that they were giving us like, 273_854 character long Strings to check...

Anyway, panicked Miss Teen USA moment, I decide to build TreeMaps, mumble something about Streams would be nice here but I'll fall back to what I am most used to because of time constraints..

I sort of time out, sort of finish, they seem less than impressed.

As soon as they let me go, of course I write what I imagined in my head but couldn't type fast enough.

I guess I have two questions.  Is this an okay usage of Streams?  Is there any point in doing this rather than just sorting the two arrays and comparing, or would you only do it to show "Look, I know how (or am showing you how) to use Streams?"



 
Saloon Keeper
Posts: 8447
71
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I don't think streams is an issue. I would think HashMap would be more efficient. I think you should probably preprocess the strings to remove non-letter characters  and to coerce the characters to lower case.
 
Jesse Silverman
Bartender
Posts: 1035
31
Eclipse IDE Postgres Database C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Right.  You CAN compare two arbitrary HashMaps for equality.
That returns true if the EntrySet's are equals(), which in turn uses the general definition of .equals() for Set, which means there is nothing to worry about there.

I think the problem I remembered doing had some weird follow-up questions like "What is the smallest change you could do to make them anagrams, if they are not..."

I did mention those other things you brought up (and had thrown them into HashMap as well) on the interview question, at least.
 
Master Rancher
Posts: 4001
52
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think using Streams is fine - but simply sorting the chars and using equals also would have worked, and been similar in performance.  In a situation like that you're best off doing the simplest thing that works.

It's also possible that Streams are less familiar to the interviewers than more traditional techniques are.  Hard to guess in advance.

Jesse Silverman wrote:


This looks clunky, why not this?


Jesse Silverman wrote:


If you look at the implementation of equals() inherited from AbstractMap, they check size() early on anyway, so we're not really improving anything here.

Like Carey, I don't think there's any benefit to using TreeMap specifically - it's slightly slower than HashMap, with no benefit in this case.

My own version of that code would be something like this:
 
Jesse Silverman
Bartender
Posts: 1035
31
Eclipse IDE Postgres Database C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Carey Brown wrote:I don't think streams is an issue. I would think HashMap would be more efficient. I think you should probably preprocess the strings to remove non-letter characters  and to coerce the characters to lower case.



In the Streams or not?  I am practicing Streams, Streams and Streams, so I changed my code to this:



EDIT -- fixed stupid Cut-and-Paste error
 
Saloon Keeper
Posts: 13182
286
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You mean, is it fine to use streams so you can use groupingBy to create a histogram of characters? Absolutely, and this would have been my first and only approach. Not only is building a histogram in the O(n) time complexity class (if you use HashMap for the histogram), it's in the O(m) space complexity class; where n is the length of the string and m is the number of distinct characters.

I'm more vexed that you didn't write a separate method to create the histogram, and your use of TreeMap instead of HashMap, which needlessly expands your time complexity class and decreases readability of your code.

I'm also not a fan of early returns for the sake of unquantified performance gains. The amount of time that a programmer spends to read your early return is likely greater than the amount of runtime you save. More important is that you check preconditions, such as your strings being non-null.

Finally, why did you make everything public? It shows you're doing this habitually, and it's a bad habit.
 
Mike Simmons
Master Rancher
Posts: 4001
52
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Regarding throwing out non-alphabetic characters - well we  can do that or not, depending on how the requirements define an anagram.  But if you do it, you probably shouldn't also return false if s1.length() != s2.length().  You could have two strings that are anagrams, except that one has an extra non-alpha character.  If you intend to ignore the non-alpha character, don't check the string length before you remove it.
 
Carey Brown
Saloon Keeper
Posts: 8447
71
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jesse Silverman wrote:

The comparison on line 4 precedes the filters on lines 7 and 11.
 
Carey Brown
Saloon Keeper
Posts: 8447
71
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:I'm more vexed that you didn't write a separate method to create the histogram

yes
 
Stephan van Hulst
Saloon Keeper
Posts: 13182
286
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote:If you intend to ignore the non-alpha character, don't check the string length before you remove it.


The same goes for Character::toLowerCase, but it has an additional problem: its behavior depends on the system locale.
 
Mike Simmons
Master Rancher
Posts: 4001
52
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:More important is that you check preconditions, such as your strings being non-null.


I tend to think that the appropriate response to a null input is to throw a NullPointerException anyway.  So this one doesn't bother me so much. But it is the sort of thing that's worth discussing with the interviewer, at least briefly.  In some environments and cultures, you need to handle nulls gracefully; in others, you can take a zero-tolerance approach.  If I were the interviewer, I would like to see that the candidate (a) thinks of these things, and (b) is flexible about how to deal with it, rather than dogmatic.

In my current job, much of the data we deal with comes from a database with no integrity checks, so just about everything needs null checks whenever we access it.  I find it very annoying.  But if you can take a zero-tolerance approach to most nulls, then you can often catch errors more quickly.
 
Mike Simmons
Master Rancher
Posts: 4001
52
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:

Mike Simmons wrote:If you intend to ignore the non-alpha character, don't check the string length before you remove it.


The same goes for Character::toLowerCase, but it has an additional problem: its behavior depends on the system locale.


No... String.toLowerCase() is Locale-dependent, but Character.toLowerCase() is not.  Though I will concede that might mean String's method is the better one to use here.  This goes back again to how do we want to define anagram.

I do see that it's theoretically possible that toLowerCase could change the length of one string but not the other, which I overlooked originally.  So yes, best to skip that early exit based on length check; it's unreliable.  We need to wait until after character filtering at least... and it's unclear whether it would be worth the trouble, by then - I already argued to drop the later length check.
 
Stephan van Hulst
Saloon Keeper
Posts: 13182
286
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Aye, I was confused with String.toLowerCase().

Character.toLowerCase() is very English-centric. It won't work well for Turkish anagrams.

My preferred solution would be to let the user decide how to compare characters using a Collator:
 
Jesse Silverman
Bartender
Posts: 1035
31
Eclipse IDE Postgres Database C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks guys.  Several very useful things I am more likely to remember than if I just read them out of a book, and less embarrassing than hearing them from someone who has to do my next review at work.

The Null Pointer thing is funny.  I heard people overselling how Java solved all the problems that constantly plagued my life with pointers, a lot.

Okay, they solved most of them.  Dangling pointers pretty much aren't a thing, I think, memory leaks are possible despite many thinking they aren't...I had given examples of what most people call memory leaks in Java that I considered accidental hoarding, like sloppy caching that keeps data around like a hoarder keeps...stuff, but there are some weird cases that sound pretty real...

Oh, right -- but NullPointerExceptions, Wow, those still happen A LOT, and more so depending on the company you keep.  And they aren't even NullReferenceException, like in that other language.  We have no pointers but null pointers...

I'm a fair fan of Optional<T> now, as long as you only use it in places nature intended it.

Yeah, thanks!
 
Sheriff
Posts: 16578
277
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:


I would probably try:

Or something along those lines. To me, creating a histogram is an implementation detail. I'd rather let the code speak to its intent.
 
Stephan van Hulst
Saloon Keeper
Posts: 13182
286
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Junilu Lacar wrote:To me, creating a histogram is an implementation detail. I'd rather let the code speak to its intent.


I think you've gone too far down the rabbit hole. I'm implementing a method. Of course I'm allowed to use implementation details. Nowhere do I leak that I'm creating a histogram to determine whether two strings are anagrams.

A histogram is exactly what I need, and it's exactly what the method returns. A name like lettersIn implies that it returns a set of characters, which is not what I want, and which would confuse anybody who's trying to understand how isAnagram() works, without also diving into the implementation of lettersIn().

More accurate than lettersIn() would be frequencyPerCharacter(), but that's really just a synonym for "histogram".
 
Junilu Lacar
Sheriff
Posts: 16578
277
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Fair enough, and you're exactly right about leaking abstractions being the concern.

What I was really going for was a more fluent way to express the idea of what an anagram is. I thought the refactoring you showed was great (should have said so up front) and was trying to take one more step toward clearly expressing intent.

How about this?

Of course, if "histogram" is something that we really like then maybe I could live with something like

Then there's also the question of expressing the opinion of whether a word is a trivial anagram of itself. The internet seems a little split on this so it seems to me the code should express its opinion on this nuance.
 
Junilu Lacar
Sheriff
Posts: 16578
277
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:

Junilu Lacar wrote:To me, creating a histogram is an implementation detail. I'd rather let the code speak to its intent.


I think you've gone too far down the rabbit hole. I'm implementing a method. Of course I'm allowed to use implementation details. Nowhere do I leak that I'm creating a histogram to determine whether two strings are anagrams.


Here's my thought process, some of it influenced by what you've already shown:

1. The main question is "Given two words, are they anagrams of each other?"
2. What are the basic input requirements? Non-null?
3. Is a word an anagram of itself? What's our opinion on this?
4. Do all characters match up, including their counts?

The reason I say a histogram is more of an implementation detail is because it's one way of figuring out if two words are anagrams. Another implementation might be that you sort the characters in both words and compare them. If they're equal, then you have anagrams. So, if I were to keep isAnagram() a fully composed method, it would probably look something like this:

To me, this is a sufficiently high-level abstraction of how I'd evaluate for anagrams; it doesn't say anything about creating a histogram or sorting or matching or whatever the calculation might be. That would be expressed in allLettersOf() or whatever we end up agreeing on how best to express the calculation.

 
Junilu Lacar
Sheriff
Posts: 16578
277
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I might also play with this design:

Maybe it's going a step too far but I can imagine it being amenable to adding some of the other nuances already discussed. Plus, the testing part.
 
Jesse Silverman
Bartender
Posts: 1035
31
Eclipse IDE Postgres Database C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Junilu Lacar wrote:I might also play with this design:

Maybe it's going a step too far but I can imagine it being amenable to adding some of the other nuances already discussed. Plus, the testing part.



I might play with it too, but not on an interview.

In retrospect, I should have done sort sort equals stated Order n log n and been done with it.
If I came up with the neater Streams version that made the histogram that would have been okay too.

The take-home is that once I learn how to do all the things I can now do with Streams slowly more quickly, I think they will often result in more readable, easier to not have to debug code.
That is, a complex stream may be tricky to debug, but enough things become so clear and simple that you never have to debug them, it just works.

I have Crossed The Line.  I now see how as much as we've been trained to go round-and-round in loops, code that can be read straight thru from top to bottom is inherently more readable and easier to grok at a glance.

People who feel differently are likely experiencing the same phenomenon as someone who thinks C is easier than Java because they have been doing C every day for 30 years.  It isn't, you are just more familiar with it, in both cases.  I now inherently feel this is true, rather than a quote from someone else that I am repeating.  I have been hearing "No explicit for loops!" from Very Respected People for a decade now in various languages, and have finally internalized it.  And I wrote my first nested loops eight years before I was legally allowed to buy a beer, and in a total of about five or six languages before that time as well.

I haven't lost a taste for "while" loops, we will see whether that happens or not.
(I've been warned about dropWhile() and takeWhile() behavior in parallel streams...it is a little too easy to carry older mindsets forward here.)

Anyway, thanks.  I feel like I am about to push over a precipice where I don't just think Streams are easier and more readable, but they will actually come out of my mind and thru my fingertips faster than the explicit for loops I've been doing millions of times for decades.
 
Junilu Lacar
Sheriff
Posts: 16578
277
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jesse Silverman wrote:I have been hearing "No explicit for loops!" from Very Respected People for a decade now in various languages, and have finally internalized it.


How I interpret that is "intent over implementation". You do still have loops in declarative programming, they're just pushed down deeper into the bowels of the implementation.

This imperative code is nice:

But equivalent functional-style code expresses intent more fluently:
 
Saloon Keeper
Posts: 24189
166
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The problem with explicit loops is that they imply serial operation. These days it's better not to force serial processing onto operations that could just as well be run in parallel.

My ├Žsthetic senses were offended by two items in your example.

First, your comparison method is what I like to call a "filtered method" in that the very first thing it does is determine whether it in fact wants to do anything at all and bails if not. Well and good, if not necessarily done in the most modern style, but I do mark it down because you didn't include the conditional predicate in braces. That's something I don't recommend since it can get you into big troouble.

More egregiously, there's the blatant copypasta in the calling method. I prefer

I've probably botched the 2-dimensional array and its enumeration, but I hope the idea is clear.
 
Jesse Silverman
Bartender
Posts: 1035
31
Eclipse IDE Postgres Database C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tim Holloway wrote:The problem with explicit loops is that they imply serial operation. These days it's better not to force serial processing onto operations that could just as well be run in parallel.



I agree with the second part, and that may indeed be the reason that the Java crew "bit the wax tadpole" and made such sweeping changes to the language but don't think that is the only perceived problem with explicit loops.

The fact that the approach focuses on intent and can be read from top to bottom seems to be important to many, and eventually they got thru to me.

I still see a lot of people just saying "We can do in parallel, so it's faster!" without really explaining how that will often not be true, and to identify the cases where it will be -- basically where the additional overhead of splitting and re-assembly is paid back with decreased wall clock time because there is enough data, or enough expense involved in processing individual elements, to pay you back (in decreased wall clock time, usually NOT in total CPU costs).

There are still soft benefits from using Streams or similar programming techniques in other languages involving readability and seeing whether something is correct or not just by looking at it for cases that will never benefit from parallel streams.  I have either got to the point that I see that now, or have become convinced of these illusory benefits, I'm not sure which.
 
Junilu Lacar
Sheriff
Posts: 16578
277
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jesse Silverman wrote:The fact that the approach focuses on intent and can be read from top to bottom seems to be important to many, and eventually they got thru to me...There are still soft benefits from using Streams or similar programming techniques in other languages involving readability and seeing whether something is correct or not just by looking at it for cases that will never benefit from parallel streams.


Readability of code is very important to those who know that code is read many more times than it is written (another case of the famous 80-20 rule). Therefore, a great amount of developer time can be saved by making code easy to understand and reason about. This is why good tests are important because they help you understand what was intended. This means that it's also important to make the tests readable and expressive of intent.
 
Jesse Silverman
Bartender
Posts: 1035
31
Eclipse IDE Postgres Database C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Junilu Lacar wrote:

Jesse Silverman wrote:I have been hearing "No explicit for loops!" from Very Respected People for a decade now in various languages, and have finally internalized it.


How I interpret that is "intent over implementation". You do still have loops in declarative programming, they're just pushed down deeper into the bowels of the implementation.

This imperative code is nice:

But equivalent functional-style code expresses intent more fluently:



I agree, but can we not do this in that case as well?


If we have a whole pipeline of intermediate operations (or even one) we obviously want what you showed in the second.

The caution about how not to abuse it reads thusly from the Javadocs:
The behavior of this method is unspecified if the action performs side-effects that modify the underlying source of elements, unless an overriding class has specified a concurrent modification policy.
So, probably, don't do THAT.

What are the plusses and minuses for what I just did versus your second example presuming we don't modify the underlying source of elements?

I can come up with one right away: "Ah, you thought you needed no intermediate operations, but you soon will realize you do, and wind up going back to the .stream() version anyway"

.forEach() has been added not just to Collection interface in Java 8+, but all the way back to Iterable

I know that for example, it is way more efficient to call .removeIf() to modify an ArrayList in place, because there is cool, funky, tested-to-heck code in there in that case to do way better than pulling the whole rest of the elements one by one each place it removes one, which would take me a month to write, test and debug.  So using a ListIterator to do an in-place conditional removal operation is both harder to read AND slower.

I don't know of other cases where there are relatively newer (Java 8+) in-place operations on Collection types that have advantages over earlier idioms and possibly (in some real use cases) over jumping to the Streams domain, I suspect there may be tho.

Basically, the same huge work they did to facilitate Streams also opened up some other new possibilities for working with Collection types that get less attention.  In my mind, I should never use a ListIterator, explicit test and explicit .remove() where I could do a .removeIf() and was wondering if there were others.

I also find myself doing a .forEach() sometimes on a Collection and wondering if I would benefit in any way from jumping to a .stream() because I am thinking that single Consumer<T> is all that I need to do with it (okay, for now at least).

 
Jesse Silverman
Bartender
Posts: 1035
31
Eclipse IDE Postgres Database C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I realized after I posted that someone might consider a developer Streams-Happy (a weird at least American phrase that I probably should have written in the thread-title with the hyphen, it is a construction like "X-Crazy" from the 1950's, but less offensive to mental health advocates)...

That someone who automatically always writes:
myCollection.stream().forEach(myPred);

in preference of:
myCollection.forEach(myPred);

Might be deemed "Streams-Happy".

As .forEach() often implies side effects that might care about ordering as in encounter-ordering, I don't know how often the fact that the first could be:
myCollection.parallelStream().forEach(myPred);

is helpful.  I guess whenever the Collection is quite large and the ordering of the side effects is of no concern to us?
 
Junilu Lacar
Sheriff
Posts: 16578
277
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jesse Silverman wrote:

Junilu Lacar wrote:...But equivalent functional-style code expresses intent more fluently:


I agree, but can we not do this in that case as well?


Yes, of course, assuming someCollection also implements the Iterable interface. A better name might have been someIterable rather than someCollection.
 
Junilu Lacar
Sheriff
Posts: 16578
277
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jesse Silverman wrote:That someone who automatically always writes:
myCollection.stream().forEach(myPred);

in preference of:
myCollection.forEach(myPred);

Might be deemed "Streams-Happy".


I don't really care about labels like that or worry about what other people think. What I'm concerned with is succinctness in code. The whole "Sorry this letter is so long, I didn't have time to write a shorter one." is where I'm coming from. So, if the latter form (the one you suggested) is all we need, then I'd prefer that over the former one (the one I automatically gave). Also, myPred is probably not a good name for that parameter as it makes me think "What does that myPred stand for, 'my Predicate'? But forEach doesn't take a Predicate, it takes a Consumer, doesn't it?"
 
Jesse Silverman
Bartender
Posts: 1035
31
Eclipse IDE Postgres Database C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Junilu Lacar wrote:
I don't really care about labels like that or worry about what other people think. What I'm concerned with is succinctness in code. The whole "Sorry this letter is so long, I didn't have time to write a shorter one." is where I'm coming from. So, if the latter form (the one you suggested) is all we need, then I'd prefer that over the former one (the one I automatically gave). Also, myPred is probably not a good name for that parameter as it makes me think "What does that myPred stand for, 'my Predicate'? But forEach doesn't take a Predicate, it takes a Consumer, doesn't it?"



Doh!!  I didn't have time to write a shorter post, but rushed and did so anyway.  I've been trying to write shorter ones and am often pressed for time.
Of course, I meant to type myConsumer, but still had .removeIf() on the brain, because that is just so cool when you want to remove elements matching a Predicate, in place.

So, wondering if .forEach() might run faster or slower than .stream().forEach(), bad.
Wondering if .forEach() might be more readable than .stream.forEach(), good -- and answer is "Yup, that is shorter for sure."?
 
Tim Holloway
Saloon Keeper
Posts: 24189
166
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The other reason why looping might be discouraged is that it is by nature not declarative.

Probably the greatest distinctions in software are those between declarative and active code. Declarative code is good because it comes with pre-defined constraints and therefore can be completely checked at compile time. Also because it has such limited syntax, it's easier to produce optimal processes.

Its strength is also its weakness - you can do anything in declarative code as long as a declaration has been defined for it. You can do anything in active code, however. The stream approach is semi-declarative, so it's natural to want to be able to make the sourcing of iterable collections be declarative as well if for consistency's sake if nothing else.
 
Jesse Silverman
Bartender
Posts: 1035
31
Eclipse IDE Postgres Database C++ Java
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tim Holloway wrote:...

Probably the greatest distinctions in software are those between declarative and active code. Declarative code is good because it comes with pre-defined constraints and therefore can be completely checked at compile time. Also because it has such limited syntax, it's easier to produce optimal processes.

Its strength is also its weakness - you can do anything in declarative code as long as a declaration has been defined for it. You can do anything in active code, however. The stream approach is semi-declarative, so it's natural to want to be able to make the sourcing of iterable collections be declarative as well if for consistency's sake if nothing else.



I think this is cross-posting between threads, but my resident Java Expert several years back used to (I think) describe the difference between Gradle and Ant thusly.
Gradle makes it super-easy to do the normal things so very succinctly.
Ant lets you do pretty much anything, but usually you don't want to do "pretty much anything" you want to do the normal thing...then you would prefer Gradle and find Ant "annoying"...
 
Tim Holloway
Saloon Keeper
Posts: 24189
166
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yup. That's about the way of it.
 
He puts the "turd" in "saturday". Speaking of which, have you smelled this tiny ad?
the value of filler advertising in 2021
https://coderanch.com/t/730886/filler-advertising
reply
    Bookmark Topic Watch Topic
  • New Topic