Java中的大量常量

Lar*_*s D 15 java android

我需要在Java应用程序中包含大约1 MB的数据,以便在其余的源代码中快速方便地访问.我的主要背景不是Java,所以我最初的想法是将数据直接转换为Java源代码,定义1MByte的常量数组,类(而不是C++ struct)等,如下所示:

public final/immutable/const MyClass MyList[] = { 
  { 23012, 22, "Hamburger"} , 
  { 28375, 123, "Kieler"}
};
Run Code Online (Sandbox Code Playgroud)

但是,似乎Java不支持这样的结构.它是否正确?如果是,那么这个问题的最佳解决方案是什么?

注意:数据由2个表组成,每个表有大约50000个数据记录,可以通过各种方式进行搜索.这可能需要稍后的一些索引,以这种方式保存更多的记录,可能是100万条记录.我希望应用程序启动速度非常快,而不会遍历这些记录.

Jon*_*eet 22

我个人不会把它放在源代码中.

相反,在jar文件中以适当的原始格式包含数据(我假设您将打包应用程序或库)并使用Class.getResourceAsStreamClassLoader.getResourceAsStream加载它.

你可能希望一个类封装加载,缓存和提供这些数据 - 但我没有看到将它转换为源代码的好处.

  • @Lars:对于K/V对,*.key = value*在`.properties`文件中(检查javadoc为`Properties`类),对于列表,只有天空是极限,虽然我建议你使用适合你的简单需要.如果你愿意,也许是XML,但通常这不是必需的. (2认同)
  • @Lars D - 如果你想避免解析XML或JSON结构化数据,你可以使用`DataInputStream`来读取原始数据格式或使用Java序列化保存数据. (2认同)
  • 对于阅读此内容的任何人都要注意:附加到资源的原始文件是压缩的,只能按顺序读取,没有随机访问. (2认同)

aio*_*obe 7

由于java字节码文件的限制,类文件不能大于64k iirc.(它们根本不适用于此类数据.)

我会在启动程序时加载数据,使用类似下面的代码行:

import java.io.*;
import java.util.*;

public class Test {
    public static void main(String... args) throws IOException {
        List<DataRecord> records = new ArrayList<DataRecord>();
        BufferedReader br = new BufferedReader(new FileReader("data.txt"));
        String s;
        while ((s = br.readLine()) != null) {
            String[] arr = s.split(" ");
            int i = Integer.parseInt(arr[0]);
            int j = Integer.parseInt(arr[1]);
            records.add(new DataRecord(i, j, arr[0]));
        }
    }
}


class DataRecord {
    public final int i, j;
    public final String s;
    public DataRecord(int i, int j, String s) {
        this.i = i;
        this.j = j;
        this.s = s;
    }
}
Run Code Online (Sandbox Code Playgroud)

(注意:扫描仪非常慢,所以不要因为它有一个简单的界面而使用它.坚持使用某种形式的BufferedReader和split,或者StringTokenizer.)

如果将数据转换为二进制格式,当然可以提高效率.在这种情况下,你可以使用DataInputStream(但不要忘记通过一些BufferedInputStreamBufferedReader)

根据您希望如何访问数据,最好将记录存储在hash-map(HashMap<Integer, DataRecord>)中(具有ij作为键).

如果您希望在JVM加载类文件本身的同时加载数据(大致!),您可以进行读取/初始化,而不是在方法中,而是在封装中static { ... }.


对于内存映射方法,请查看java.nio.channelsjava 中的-package.特别是方法

public abstract MappedByteBuffer map(FileChannel.MapMode mode, long position,long size) throws IOException

完整的代码示例可以在这里找到.


Dan Bornstein(DalvikVM的首席开发人员)在本次演讲中解释了您的问题解决方案(请查看0:30:00左右).但是我怀疑这个解决方案适用于兆字节数据.