如何从 4,000,000,000 个号码中获取最常用的 100 个号码?
昨天在一次编码面试中,我被问及如何从4,000,000,000个整数(可能包含重复项)中获取最常见的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 个值?