If you are going to do this in a constant number of passes over the list, you need a second data structure.
If you have lower and upper bounds for the values in that set and the values are relatively dense, then an array of counters is a good solution.
Otherwise, it is better to use a Map<Integer, Integer>
, where the keys are elements of the set and the values are counters.
Analysis
If you don't have lower / upper bounds on the set before you start, then you don't know big an array of counters to allocate. So you have to make a preliminary pass over the array to find the bounds ... and you now have a two pass solution.
If you do have lower and upper bounds but the set is sparse, then the cost of initializing the array of counts + the cost of finding the three largest counts will dominate the cost of counting the set elements. If the difference is large enough (i.e. the input is large & very sparse) a HashMap will be faster and will take less memory.
Alternatively
If you are allowed to change the array, you can sort it into ascending order O(NlogN)
and then find the three most common elements in a single pass over the sorted array.