Reputation: 357
i have a HashMap resultdata like below
"zip000", 1234
"zip001", 2345
"zip002", 3456
"zip003", 4567
"zip004", 7890
"zip005", 7890
"zip006", 123
"zip007", 234
"zip010", 7890
"zip011", 678
"zip012", 789
"zip013", 890
and used below code
public static List<String> topNKeys(final HashMap<String, Integer> map, int n) {
PriorityQueue<String> topN = new PriorityQueue<String>(n, new Comparator<String>() {
public int compare(String s1, String s2) {
return Integer.compare(map.get(s1), map.get(s2));
}
});
for(String key:map.keySet()){
if (topN.size() < n)
topN.add(key);
else if (map.get(topN.peek()) < map.get(key)) {
topN.poll();
topN.add(key);
}
}
return (List) Arrays.asList(topN.toArray());
}
Above code displays me topN records as
Assume n= 6
zip001=2345
zip002=3456
zip003=4567
zip005=7890
zip010=7890
zip004=7890
But i need it to give all top 6 resultdata according to Integer Rank, i mean like below
zip013=890
zip000=1234
zip001=2345
zip002=3456
zip003=4567
zip005=7890
zip010=7890
zip004=7890
According to integers where 7890,4567,3456,2345,1234,890 are the top 5 Integers.
How could i do this? Any kind of help and suggestion is appreciated.
Upvotes: 0
Views: 796
Reputation: 328835
You could do it in two steps:
In terms of code, you could write it like this:
public static List<Entry<String, Integer>> topNKeys(Map<String, Integer> map, int n) {
Set<Integer> topValues = getTopValues(map, n);
return getEntriesWithTopValues(map, topValues);
}
//Returns the distinct top n values
private static Set<Integer> getTopValues(Map<String, Integer> map, int n) {
TreeSet<Integer> values = new TreeSet<>(map.values());
Set<Integer> topNValues = new HashSet<>();
for (int i = 0; i < n; i++) {
Integer v = values.pollLast();
if (v != null) topNValues.add(v);
else break;
}
return topNValues;
}
//Returns the entries with a value that is contained in topValues
private static List<Entry<String, Integer>> getEntriesWithTopValues(Map<String, Integer> map, Set<Integer> topValues) {
return map.entrySet().stream()
.filter(e -> topValues.contains(e.getValue()))
.sorted(Entry.comparingByValue())
.collect(toList());
}
Applied to your example, it returns the desired output.
Without stream, the last method could be written:
private static List<Entry<String, Integer>> getEntriesWithTopValues(Map<String, Integer> map, Set<Integer> topValues) {
List<Entry<String, Integer>> result = new ArrayList<> ();
for (Entry<String, Integer> e : map.entrySet()) {
if (topValues.contains(e.getValue())) result.add(e);
}
Collections.sort(result, new Comparator<Entry<String, Integer>>() {
@Override
public int compare(Entry<String, Integer> e1, Entry<String, Integer> e2) {
return e1.getValue().compareTo(e2.getValue());
}
});
return result;
}
Upvotes: 2