0

我正在为我的大学重构一小部分开源大型配置管理系统。

我们正在使用一些开源工具进行机器学习,比如 Weka,而我被分配重构的方面是处理数据挖掘和构建规则。

我们一直使用的利物浦和日本的开源文件运行良好,但是当我们在大型项目中使用该程序时会出现一些内存使用问题。

我已经隔离了主要的内存消耗并得出结论,我需要找出不同的数据结构来存储和操作数据。就目前而言,该程序正在使用最终变成非常大的整数、对象、字符串等多维数组。

在我们推导出行为规则之后,有几种方法可以简单地重新配置关联的设置。在许多情况下,我们只是添加或减去单个元素,或者只是将多维数组展平。

一般来说,我主要使用 C/C++ 进行编程,所以我不是 Java 中可用数据结构的专家。我希望用一个动态结构来替换静态数组,该结构可以轻松调整大小,而无需创建第二个多维数组。

现在发生的情况是,每次从多维数组中添加和删除规则、对象或其他杂项数据时,我们都必须创建一个全新的结构。然后我们立即复制到新数组中。

我希望能够简单地使用相同的多维数组并简单地添加新的行和列。随后,我希望能够通过简单地保存临时值并覆盖以前的值、左移、右移等来操作结构中的数据。

谁能想到 Java 中任何符合要求的数据结构?

在相关的说明中,我研究了显式垃圾收集,但发现我只能通过调用 System.Gc() 或通过调整来操纵 JVM 的垃圾收集行为来真正建议 JVM 收集。有没有更好或更有效的方法?

问候, 埃德姆

4

5 回答 5

1

如果矩阵中有很多空值/零值/假值/空字符串,则可以使用稀疏矩阵实现来节省空间。 Matrix-toolkits有几个稀疏矩阵,您可以使用/修改以满足您的需要,或者您可以只使用带有 {x, y} 元组作为键的哈希图。(hashmap 的另一个优点是有几个可用的外部 hashmap 实现,例如BerkeleyDB,因此您不太可能耗尽内存。)

于 2013-06-26T04:38:24.650 回答
1

要使用动态结构替换静态数组,请使用ArrayList随数据自动增长的 an。要具有二维数据结构,请使用 a Listof Listas

List<List<Integer>> dataStore = new ArrayList<List<Integer>>();
dataStore.add(new ArrayList<Integer>());
dataStore.add(Arrays.asList(1, 2, 3, 4));

// Access [1][3] as
System.out.println(dataStore.get(1).get(3)); // prints 4

因为,您谈到了对垃圾收集的控制(Java 实际上本身就做得很好),所以内存管理似乎是最重要的,因为这首先是导致重构的原因。

您可以查看Flyweight专注于共享对象而不是重复它们以减少应用程序的内存占用的 GoF 模式。要启用共享享元对象,需要将其设为不可变

伪代码:

// adding a new flyweight obj at [2][1]
fwObjStore.get(2).set(1, FWObjFactory.getInstance(fwKey));

public class FWObjFactory {
    private static Map<String, FWObject> fwMap = new HashMap<String, FWObject>();

    public static getInstance(String fwKey) {
        if (!fwMap.containsKey(fwKey)) {
            fwMap.put(fwKey, newFwFromKey(fwKey));
        }
        return fwMap.get(fwKey);
    }

    private static FWObject newFwFromKey(String fwKey) {
        // ...
    }
}
于 2013-06-26T04:40:52.570 回答
0

Java 中没有多维的东西。Java 有数组。

您可以将带有类型参数的 ArrayList 用作ArrayList

ArrayList<ArrayList<yourType>> myList = new ArrayList<ArrayList<yourType>>();

另外,不用担心 GC ..它会在需要时收集..

于 2013-06-26T04:30:03.467 回答
0

我会考虑使用“列表列表”。例如,您可以声明类似

List<List<Object>> mArray = new ArrayList<List<Object>>();

每当您需要添加新的“行”时,您可以执行以下操作:

mArray.add (new ArrayList<Object>());

查看List接口以了解您可以List在 Java 中使用 s 做什么以及哪些类实现了该接口(或推出您自己的接口!)。

于 2013-06-26T04:34:41.010 回答
0

为什么不使用两个Lists纠缠在一起?像这样:

List<List<String>> rowColumns = new ArrayList<>();

// Add a row with two entries, or columns:
List<String> oneRow = Arrays.asList("Hello", "World!");
rowColumns.add(oneRow);

此外,考虑使用映射到列表的条目的映射。

垃圾收集通常永远不必在 Java 中显式处理。通常,您希望在第一次发生内存泄漏时查找内存泄漏。发生这种情况时,请在缓存中寻找不会死掉的后台线程或强引用。如果您想阅读有关后一问题的一些信息,可以从此处此处开始。

于 2013-06-26T04:39:18.227 回答