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.
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.
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...
posted 6 months ago
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 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.