J'ai une technique très spécifique que j'utilise pour ce genre de chose. C'est en quelque sorte une approche hybride que je trouve aboutit au code io de base le plus performant, tout en maintenant la lisibilité et la compatibilité avec la sérialisation Java.
La réflexion utilisé dans la sérialisation Java a été la partie qui a été pensé historiquement à être lent, et il était lent. Mais depuis l'ajout de sun.misc.Unsafe
, cette partie est en réalité incroyablement rapide. Il y a toujours le hit initial du tout premier appel à clazz.getDeclaredFields() et d'autres méthodes de type 'getDeclared' de java.lang.Class, mais ceux-ci sont mis en cache au niveau de la VM, ils sont donc peu coûteux après le premier (très perceptible) frappé.
Les frais généraux restant de sérialisation Java est l'écriture de données de descripteur de classe; le nom de la classe, les champs et les types, etc.Si les objets java étaient en XML, ce serait comme écrire d'abord le xsd pour que la structure soit connue, puis écrire les données xml sans les balises. Il est en fait très performant dans certaines situations, par exemple si vous avez besoin d'écrire plus de 100 instances du même type de classe dans le même flux - vous ne sentirez jamais l'impact des données des descripteurs de classes en même temps. début du flux. Mais si vous avez juste besoin d'écrire une instance de cette classe et peut-être pas grand-chose d'autre, il existe un moyen d'inverser les choses à votre avantage. Au lieu de transmettre votre objet au flux, ce qui entraîne la première écriture du descripteur de classe suivi des données réelles, passez le flux à l'objet et passez directement à la partie d'écriture des données. Bottom line est que vous prenez la responsabilité de la partie de la structure dans votre code plutôt que d'avoir le ObjectOutput/ObjectInput le faire. Remarque, j'ai également renommé votre classe de Map
à TileMap
. Comme le souligne BalusC, ce n'est pas un bon nom de classe.
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();
}
}
}
}
Une écriture ressemblerait à ceci:
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();
}
Et une lecture ressemblerait à ceci:
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;
}
A pris note devrait être qu'il existe un 'utilisé java.util très commun. Carte' classe. Vous aimeriez renommer votre classe 'Map' en quelque chose de différent pour éviter les conflits de noms et les confusions d'autres développeurs (re) visualisant votre code. – BalusC