Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/211.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中的大量常量_Java_Android - Fatal编程技术网

Java中的大量常量

Java中的大量常量,java,android,Java,Android,我需要在Java应用程序中包含大约1Mbyte的数据,以便在其余的源代码中快速方便地访问。我的主要背景不是java,所以我的最初想法是直接把数据转换成java源代码,定义常数数组的1MbEy,类(而不是C++结构)等等,类似这样的: public final/immutable/const MyClass MyList[] = { { 23012, 22, "Hamburger"} , { 28375, 123, "Kieler"} }; 然而,Java似乎不支持这种构造。这是正确

我需要在Java应用程序中包含大约1Mbyte的数据,以便在其余的源代码中快速方便地访问。我的主要背景不是java,所以我的最初想法是直接把数据转换成java源代码,定义常数数组的1MbEy,类(而不是C++结构)等等,类似这样的:

public final/immutable/const MyClass MyList[] = { 
  { 23012, 22, "Hamburger"} , 
  { 28375, 123, "Kieler"}
};
然而,Java似乎不支持这种构造。这是正确的吗?如果是,这个问题的最佳解决方案是什么


注:数据由2个表组成,每个表约有50000条数据记录,需要以各种方式进行搜索。这以后可能需要一些索引,以这种方式保存更多的记录,可能有100万条记录。我希望应用程序能够快速启动,而无需遍历这些记录。

一个想法是使用枚举数,但我不确定这是否适合您的实现,这还取决于您计划如何使用数据

public enum Stuff {

 HAMBURGER (23012, 22),
 KIELER    (28375, 123);

 private int a;
 private int b;

 //private instantiation, does not need to be called explicitly.
 private Stuff(int a, int b) {
    this.a = a;
    this.b = b;
  }

 public int getAvalue() {
   return this.a;
 }

 public int getBvalue() {
   return this.b;
 }
}

然后可以通过以下方式访问:

Stuff someThing = Stuff.HAMBURGER;
int hamburgerA = Stuff.HAMBURGER.getA() // = 23012

另一个想法是使用初始值设定项来设置类的私有字段。

您还可以声明一个静态类(或一组静态类),将指定的值作为方法公开。毕竟,您希望代码能够找到给定名称的值,而不希望该值发生更改

所以:location=MyLibOfConstants.returnHamburgerLocation().zipcode

你可以用lazyinitialization将这些东西存储在一个哈希表中,如果你认为动态计算会浪费时间的话。

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

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


您可能非常希望使用一个类来封装加载、缓存和提供这些数据,但我看不出将其转换为源代码有什么好处。

由于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;
    }
}
import java.io.*;
导入java.util.*;
公开课考试{
公共静态void main(字符串…参数)引发IOException{
列表记录=新的ArrayList();
BufferedReader br=新的BufferedReader(新文件读取器(“data.txt”);
字符串s;
而((s=br.readLine())!=null){
字符串[]arr=s.split(“”);
int i=Integer.parseInt(arr[0]);
int j=Integer.parseInt(arr[1]);
添加(新的数据记录(i,j,arr[0]);
}
}
}
类数据记录{
公共最终int i,j;
公共最终字符串s;
公共数据记录(int i、int j、字符串s){
这个。i=i;
这个。j=j;
这个.s=s;
}
}
(注意:扫描仪速度非常慢,所以不要仅仅因为它有一个简单的界面就尝试使用它。请使用某种形式的BufferedReader和split,或StringTokenizer。)

当然,如果将数据转换为二进制格式,效率会得到提高。在这种情况下,您可以使用
DataInputStream
(但不要忘记浏览一些
BufferedInputStream
BufferedReader

根据您希望访问数据的方式,最好将记录存储在哈希映射(
HashMap
)中(使用
i
j
作为键)

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


对于内存映射方法,请查看java中的
java.nio.channels
-包。尤其是方法

可以找到完整的代码示例


Dan Bornstein(DalvikVM的首席开发人员)在(0:30:00左右)中解释了问题的解决方案。然而,我怀疑这个解决方案是否适用于一兆字节那么多的数据

将数据直接转换为Java源代码,定义1字节的常量数组、类


请注意,类及其结构的大小有严格的限制[ref.

缓存不是您所需要的吗? 作为类,它被加载到内存中,而不限于定义的大小,应该和使用常量一样快。。。 实际上,它甚至可以使用某种索引搜索数据(例如使用对象hashcode…) 例如,您可以创建所有数据数组(例如{23012,22,“Hamburger”}),然后创建3个hashmap: map1.put(23012,汉堡市); map2.put(22,汉堡里坦); 地图3.put(“汉堡包”,汉堡包); 这样,您可以根据您拥有的参数在其中一个地图中快速搜索。。。 (但这只有在你的钥匙在地图上是唯一的情况下才有效……这只是一个可以启发你的例子)

在工作中,我们有一个非常大的webapp(80个weblogic实例),它几乎就是我们所做的:到处缓存。从数据库中的countrylist,创建一个缓存

有许多不同类型的缓存,你应该检查链接,选择你需要的。。。

如果我了解您的目标,您可以用Java来定义它:

public final Object[][] myList = { 
          { 23012, 22, "Hamburger"} , 
          { 28375, 123, "Kieler"}
        };

将数据放入源代码实际上可能不是最快的解决方案,从长远来看也不是。加载Java类相当复杂且缓慢(至少在进行字节码验证的平台上是如此,对Android不太确定)

最快的方法是定义您自己的二进制索引格式。然后您可以将其读取为
字节[]
(可能使用内存映射)甚至是一个
RandomAccessFile
,在您开始访问它之前,不以任何方式解释它。这样做的代价是访问它的代码的复杂性。对于固定大小的记录,通过二进制searc访问的记录的排序列表
class MyDataStore
{
   FileChannel fc = null;
   Map<Integer,Entry> mychace = new HashMap<Integer, Entry>();
   int chaceSize = 50000;
   ArrayList<Integer> queue = new ArrayList();
   static final int entryLength = 100;//byte
   void open(File f)throws Exception{fc = f.newByteChannel()}
   void close()throws Exception{fc.close();fc = null;}
   Entry getEntryAt(int index)
   {
       if(mychace.contains(index))return mychace.get(index);

       long pos = index * entryLength; fc.seek(pos);ByteBuffer 
       b = new ByteBuffer(100);
       fc.read(b);
       Entry a = new Entry(b);
       queue.add(index);
       mychace.put(index,a);
       if(queue.size()>chacesize)mychace.remove(queue.remove(0));
       return a;
   }

}
class Entry{
   int a; int b; String s;
   public Entry(Bytebuffer bb)
   {
     a = bb.getInt(); 
     b = bb.getInt(); 
     int size = bb.getInt();
     byte[] bin = new byte[size];
     bb.get(bin);
     s = new String(bin);
   }
}