昨天,在一次编程访谈中,我被问到如何从400万个整数(可能包含重复)中找出最常用的100个数字,例如:
813972066
908187460
365175040
120428932
908187460
504108776
我想到的第一个方法是使用 HashMap:
static void printMostFrequent100Numbers() throws FileNotFoundException {
// Group unique numbers, key=number, value=frequency
Map<String, Integer> unsorted = new HashMap<>();
try (Scanner scanner = new Scanner(new File("numbers.txt"))) {
while (scanner.hasNextLine()) {
String number = scanner.nextLine();
unsorted.put(number, unsorted.getOrDefault(number, 0) + 1);
}
}
// Sort by frequency in descending order
List<Map.Entry<String, Integer>> sorted = new LinkedList<>(unsorted.entrySet());
sorted.sort((o1, o2) -> o2.getValue().compareTo(o1.getValue()));
// Print first 100 numbers
int count = 0;
for (Map.Entry<String, Integer> entry : sorted) {
System.out.println(entry.getKey());
if (++count == 100) {
return;
}
}
}
但是它可能会对4,000,000,000个数字的数据集抛出 OutOfMemory 异常。此外,由于4,000,000,000超过了 Java 数组的最大长度,因此假设数字在文本文件中而且没有排序。我认为多线程或者 Map Reduce 更适合大数据集?
当数据不适合可用内存时,如何计算前100个值?