我有一個非常具體的技術,我用這種東西。這是一種混合方法,我可以在最高性能的基本io代碼中找到結果,但仍保持可讀性和與簡單Java序列化的兼容性。
在Java序列化中使用的反射是歷史上認爲很慢並且速度很慢的部分。但自從sun.misc.Unsafe
加入以來,這部分實際上非常快。仍然有第一次調用clazz.getDeclaredFields()和java.lang.Class的其他'getDeclared'類型方法的初始命中,但是這些方法在VM級別被緩存,所以在第一個(非常明顯的)擊中。
Java序列化的剩餘開銷是類描述符數據的寫入;類名稱,它具有的字段以及它們是什麼類型等等。如果java對象是xml,它就像首先編寫xsd,以便知道結構,然後寫入沒有標籤的xml數據。在某些情況下,它實際上是非常高效的,例如,如果您需要將100多個相同類類型的實例寫入同一個流中 - 您將永遠不會感受到一次寫入類描述符數據的衝擊流的開始。
但是,如果你只需要寫一個該類的實例,也許沒有其他的東西,那麼有一種方法可以將事物轉化爲你的優勢。不要將對象傳遞給流,這會導致類描述符首先被寫入,然後是實際數據,將流傳遞給對象並直接轉到數據寫入部分。底線是你負責代碼中的結構部分,而不是讓ObjectOutput/ObjectInput執行它。
請注意,我也將您的班級從Map
更名爲TileMap
。正如BalusC指出的那樣,這不是一個好名字。
import java.io.*;
public class TileMap implements Externalizable {
private String name;
private int[][] tiles;
public TileMap(String name, int[][] tiles) {
this.name = name;
this.tiles = tiles;
}
// no-arg constructor required for Externalization
public TileMap() {
}
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF(name);
out.writeInt(tiles.length);
for (int x = 0; x < tiles.length; x++) {
out.writeInt(tiles[x].length);
for (int y = 0; y < tiles[x].length; y++) {
out.writeInt(tiles[x][y]);
}
}
}
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
this.name = in.readUTF();
this.tiles = new int[in.readInt()][];
for (int x = 0; x < tiles.length; x++) {
tiles[x] = new int[in.readInt()];
for (int y = 0; y < tiles[x].length; y++) {
tiles[x][y] = in.readInt();
}
}
}
}
寫是這樣的:
public static void write(TileMap tileMap, OutputStream out) throws IOException {
// creating an ObjectOutputStream costs exactly 4 bytes of overhead... nothing really
final ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(out));
// Instead of oos.writeObject(titleMap1) we do this...
tileMap.writeExternal(oos);
oos.close();
}
和讀是這樣的:
public static TileMap read(InputStream in) throws IOException, ClassNotFoundException {
final ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(in));
// instantiate TileMap yourself
TileMap tileMap = new TileMap();
// again, directly call the readExternal method
tileMap.readExternal(ois);
return tileMap;
}
注意到應該是存在一個很普遍的使用'java.util中。地圖'類。您希望將您的'Map'類重命名爲不同的名稱,以避免名稱衝突和其他開發人員混淆(重新)查看您的代碼。 – BalusC 2010-09-11 20:13:29