• 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
  • Tim Cooke
  • Liutauras Vilda
  • Jeanne Boyarsky
  • paul wheaton
Sheriffs:
  • Ron McLeod
  • Devaka Cooray
  • Henry Wong
Saloon Keepers:
  • Tim Holloway
  • Stephan van Hulst
  • Carey Brown
  • Tim Moores
  • Mikalai Zaikin
Bartenders:
  • Frits Walraven

How to get frequency count of integers in a stream? (perhaps using Collectors)

 
Ranch Hand
Posts: 662
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The Lonely Integer Challenge on HackerRank is here.

Given an array of integers, where all elements but one occur twice, find the unique element.


I solved this problem in a simple way using a Set,
but I was wondering if there is a way to get frequency count of integers in a stream? (perhaps using Collectors.groupingBy()?).
I looked at the docs but could not figure out how to do it using streams and Collectors.

Note that my code is in lonelyinteger(). The rest is the framework provided by HackerRank.



 
Saloon Keeper
Posts: 10929
87
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
There's a neat little trick using XOR that will solve this efficiently. If you XOR the same numbers (i.e. a pair) together you get zero. You can go through the list XORing each integer in turn and all pairs will cancel each other out regardless of where the occur leaving the result being the one lonely integer.
 
Anil Philip
Ranch Hand
Posts: 662
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Carey Brown wrote:There's a neat little trick using XOR that will solve this efficiently. If you XOR the same numbers (i.e. a pair) together you get zero. You can go through the list XORing each integer in turn and all pairs will cancel each other out regardless of where the occur leaving the result being the one lonely integer.


And what if they are not side by side?
 
Carey Brown
Saloon Keeper
Posts: 10929
87
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
 
Anil Philip
Ranch Hand
Posts: 662
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Carey Brown wrote:"regardless of where the occur"


ok, I missed that
 
Master Rancher
Posts: 5060
81
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The XOR trick is cool and super fast, but only really works for this very specific problem. What if there were two elements that only occur once?  

I do think it's pretty useful to know how to get a frequency count of items in an array, collection, or stream.  Collectors.groupingBy() is definitely useful - but not a complete solution itself.  The standard library does provide several other methods you can combine for a fairly concise solution:
 
Anil Philip
Ranch Hand
Posts: 662
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote:The XOR trick is cool and super fast, but only really works for this very specific problem. What if there were two elements that only occur once?  


Great point!
I thought the same problem will be with the Set solution I posted above, but I am unable to get it to fail on input like

6
3 1 3 1 2 3
OR
6
2 3 1 3 1 3
OR
6
3 1 3 1 3 2

I expect it to return 3 (incorrect value) but it returns 2 (correct value).

Mike Simmons wrote:
I do think it's pretty useful to know how to get a frequency count of items in an array, collection, or stream.  Collectors.groupingBy() is definitely useful - but not a complete solution itself.  The standard library does provide several other methods you can combine for a fairly concise solution:



I am trying to understand


Does the classifier Function.identity() work only because the elements are Integers with only one attribute (their value)
- if they were objects with other attributes then we would have to supply the method Foo::getAttribute ?

Trying to step through it in the IDE, This is really formidable code!



 
Saloon Keeper
Posts: 15727
368
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Anil Philip wrote:Does the classifier Function.identity() work only because the elements are Integers with only one attribute (their value)
- if they were objects with other attributes then we would have to supply the method Foo::getAttribute ?


No.

The classifier is simply a function that converts an element of the stream to another value. That value can be (and usually is) a property of the element being converted, but it can also be something completely different.

Sometimes you don't want to convert the value, but just use the value itself. You can do it with a lambda expression:


Or you can do it with the identity() operator.

This is not limited to value types either. You can do this with any reference type.
 
Mike Simmons
Master Rancher
Posts: 5060
81
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Stephan's answer is 100% correct.  I would add: it works based on what we want to used as the key for grouping the elements.  In this case, we were using the elements themselves for grouping.  But yes, in many cases if you had an object with attributes, you would probably want to use something like Foo::getAttribute.  If you don't do that, then the grouping is done based on how equals() and hashCode() are done in whatever class you're using.  That's true in our case above too - for Integer, equals() and hashCode() have already been overridden to provide simple, sensible results that allow two different Integer instances with equal values to evaluate as equal.
 
Listen. That's my theme music. That's how I know I'm a super hero. That, and this tiny ad told me:
Gift giving made easy with the permaculture playing cards
https://coderanch.com/t/777758/Gift-giving-easy-permaculture-playing
reply
    Bookmark Topic Watch Topic
  • New Topic