重构以下代码,以利用非常小的空间,即使对于大数据也是如此



"火车有货车计数,车厢索引为 0,1,......wagonCount-1.每个车厢必须使用 fillWagon 函数填充到火车的构造函数中。它接受货车的索引并返回货车的货物。下面的代码有效,但服务器有足够的内存供小火车使用。反应堆代码,以便服务器有足够的内存,即使是大型火车?

"认为我们可以将 Hashtable 集合转换为数组,但不知道如何开始,请帮忙。或任何想法都会有很大帮助。">

import java.util.function.Function;
public class Train {
private Hashtable<Integer, Integer> wagons;
public Train(int wagonCount, Function<Integer, Integer> fillWagon) {
this.wagons = new Hashtable<Integer, Integer>();
for (int i = 0; i < wagonCount; i++) {
this.wagons.put(i, fillWagon.apply(i));
}
}
public int peekWagon(int wagonIndex) {
return this.wagons.get(wagonIndex);
}
public static void main(String[] args) {
Train train = new Train(10, wagonIndex -> wagonIndex);
for (int i = 0; i < 10; i++) {
System.out.println("Wagon: " + i + ", cargo: " + train.peekWagon(i));
}
}
}

您可以使用int[]它消耗更少的内存。 它是保留整数的最佳结构。Hashtable<Integer, Integer>具有复杂的结构和存储数字的巨大开销,即使Ineger[]消耗的内存也比 int[] 多得多。所以最好的结构是基元数组。看看 Java 对象的内存用法的良好解释。

我们使用数组索引按所需位置访问元素,而不是Hashtable.get它需要更少的 CPU 资源:

public class Train {
private int[] wagons;
public Train(int wagonCount, Function<Integer, Integer> fillWagon) {
this.wagons = new int[wagonCount];
for (int i = 0; i < wagonCount; i++) {
this.wagons[i] = fillWagon.apply(i);
}
}
public int peekWagon(int wagonIndex) {
return this.wagons[wagonIndex];
}
public static void main(String[] args) {
Train train = new Train(10, wagonIndex -> wagonIndex);
for (int i = 0; i < 10; i++) {
System.out.println("Wagon: " + i + ", cargo: " + train.peekWagon(i));
}
}
}

如果需要在构造函数执行期间填充所有 wagon,那么当内存的大小限制为某个小常量时,就没有办法在内存中存储任意数量的 wagon 内容。当然,使用int数组会比映射占用更少的内存,但它仍然会根据输入大小线性增长。

但是,如果允许延迟 wagon 内容的实际存储,则可以使用构造函数来保留对回调函数的引用,并且仅在调用peekWagon时才调用它。您仍然可以使用可用于存储某些货车内容的少量内存,但仅适用于最后查询的k节车。这样,您将在内存中拥有定期查询的内容,但是当该特定货车不在(或不再(内存中时,需要(再次(检索内容。然后,您将再次调用回调函数。

当然,这假设回调函数不会产生不良的副作用,并且在传递相同的参数时它将始终返回相同的值。

如果这些假设没问题,您的代码可能如下所示:

import java.util.*;
import java.util.function.Function;
public class Main {
static int maxSize = 4;
private LinkedHashMap<Integer, Integer> wagons;
private Function<Integer, Integer> fillWagon;
public Main(int wagonCount, Function<Integer, Integer> fillWagon) {
this.wagons = new LinkedHashMap<Integer, Integer>();
this.fillWagon = fillWagon;
}
public int peekWagon(int wagonIndex) {
int content;
if (!this.wagons.containsKey(wagonIndex)) {
if (this.wagons.size() >= maxSize) {
// Make room by removing an entry
int key = this.wagons.entrySet().iterator().next().getKey();  
this.wagons.remove(key);
}
content = this.fillWagon.apply(wagonIndex);
} else {
// Remove entry so to put it at end of LinkedHashMap
content = this.wagons.get(wagonIndex);
this.wagons.remove(wagonIndex);
}
this.wagons.put(wagonIndex, content);
return content;
}
/* ... */
}

最新更新