This week's book giveaway is in the HTML Pages with CSS and JavaScript forum.
We're giving away four copies of Testing JavaScript Applications and have Lucas da Costa on-line!
See this thread for details.
Win a copy of Testing JavaScript Applications 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 all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Bear Bibeault
  • Ron McLeod
  • Jeanne Boyarsky
  • Paul Clapham
Sheriffs:
  • Tim Cooke
  • Liutauras Vilda
  • Junilu Lacar
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • fred rosenberger
  • salvin francis
Bartenders:
  • Piet Souris
  • Frits Walraven
  • Carey Brown

.map(i -> 1).sum() preferable to .count() with IntStream?

 
Rancher
Posts: 185
25
Firefox Browser MySQL Database Java Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I wrote a method to find the Hamming distance between two strings as part of a coding exercise. I wrote the following:

A mentor suggested that I could improve my solution by getting rid of the cast, and hinted that I should look at map() and sum(). I assume they meant this:

Why would this approach be better, though? The name of the method count() is self documenting, and is just one method, verses two with map() and sum(). Is casting a code smell?
 
Ranch Hand
Posts: 89
1
VI Editor Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I dont see a problem with using count, it is exactly for that purpose. Especially when you are using IntStream, I dont see an option how you could get count which would not fit into int type.

You could also use reduce:
 
Marshal
Posts: 69847
278
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Jj Roberts wrote:. . .I could improve my solution by getting rid of the cast . . .

What is the point of the cast? Is it that Stream#count() returns a long? I suggest you make your method return a long, and let users who require an int do their own casting.

Is casting a code smell?

Not always, but in many cases, yes. I worry more if I see casts of reference types.

I see the link to count() makes a suggestion about using sum(). I agree that count() makes your code much easier to read. Why is the method you wrote an instance method? Why isn't it static?

ML: will the suggestion with reduce() give a Hamming distance?
 
Jj Roberts
Rancher
Posts: 185
25
Firefox Browser MySQL Database Java Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:

Jj Roberts wrote:. . .I could improve my solution by getting rid of the cast . . .

What is the point of the cast? Is it that Stream#count() returns a long? I suggest you make your method return a long, and let users who require an int do their own casting.

Is casting a code smell?

Not always, but in many cases, yes. I worry more if I see casts of reference types.

I see the link to count() makes a suggestion about using sum(). I agree that count() makes your code much easier to read. Why is the method you wrote an instance method? Why isn't it static?

ML: will the suggestion with reduce() give a Hamming distance?



The way the exercise is set up, the strings the method compares are actually instance fields. They are passed to a constructor inside JUnit tests. That is why my method is not static. It is also supposed to return an int, hence the need for a cast.
A while after posting I noticed that the IntStream documentation does specifically mention

count
long count()
This is a special case of a reduction and is equivalent to:
   return mapToLong(e -> 1L).sum();

Which makes .map( i -> 1).sum() the equivalent of count(), only returning an int.
 
Jj Roberts
Rancher
Posts: 185
25
Firefox Browser MySQL Database Java Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Miroslav Lehotsky wrote:You could also use reduce:

Yes, that is true, and that is one function, not two. It is less readable, though. I ran a benchmark to test .reduce(0, (sum, i) -> sum + 1) against .map(i -> 1).sum() with JMH. The result:
.map() and .sum() takes one fifth of the time .reduce() does, if my benchmark is not flawed.
 
Miroslav Lehotsky
Ranch Hand
Posts: 89
1
VI Editor Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you consider performance, then you should also consider this statement from javadoc of count method:

An implementation may choose to not execute the stream pipeline (either sequentially or in parallel) if it is capable of computing the count directly from the stream source.



Then, for example:




First version was about 50x faster than the second one for me...
 
Campbell Ritchie
Marshal
Posts: 69847
278
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Unless you have a performance problem, which I would have thought unlikely for something like Hamming distances, always go for readability. I think you are stuck with the (int) cast.
Well done showing us those JMH figures. What happens if you have a count much larger than 25?
 
Jj Roberts
Rancher
Posts: 185
25
Firefox Browser MySQL Database Java Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Jj Roberts wrote:.map() and .sum() takes one fifth of the time .reduce() does, if my benchmark is not flawed.

Well, it was. I ran the test again with larger strings and got a different result. Here is my JMH test code:
The Hamming distance for these strings is 88. The test ran five forks of five warmup and five test rounds of ten seconds each (the Cnt column gives the total number of testing rounds) for each method. The result I got wasThere is practically no difference!

I have wanted to be able to benchmark code, but I know that Java is very difficult to benchmark accurately. I found JMH the other day, and I am still trying to learn to use it.
 
Jj Roberts
Rancher
Posts: 185
25
Firefox Browser MySQL Database Java Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you for the cow!
 
Don't get me started about those stupid light bulbs.
    Bookmark Topic Watch Topic
  • New Topic