Best way to store this HashMap in a file

Discussion in 'Plugin Development' started by Baummann, Nov 22, 2011.

Thread Status:
Not open for further replies.
  1. Offline

    Baummann

    I've got a HashMap which has a Block as key and a String as value.

    How can I save it in a file?

    I've tried ObjectOutputStream but since the Block class doesn't implement Serializable I can't use that one.

    I've tried using a Object to Byte array converter and writing the byte array to a file:

    Code:
    public class ObjectConverter {
        public static byte[] convert(Object obj) throws IOException {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(obj);
            oos.flush();
            oos.close();
            return baos.toByteArray();
        }
    
        public static Object convert(byte[] bytes) throws Exception {
            Object object = null;
            ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
    
            object = ois.readObject();
    
            ois.close();
            return object;
        }
    }
    
    Same result as ObjectOutputStream.
     
  2. Offline

    halley

    What's your purpose for using a Block as a key? Is it the getLocation() of the block that matters for uniqueness in your plugin? Is it the getType() of the block that matters for uniqueness? Consider making the map key more specific to the unique characteristic of the block that matters. If even that is not serializable, it will be easier to make a serializable key from it. For example mymap.put(myBlock.getType().toString(), myString).
     
    WalkerCrouse likes this.
  3. Offline

    Baummann

    I need both, getType() and getLocation().
     
  4. Offline

    thehutch

    You can't store a location in a hashMap :(
     
  5. Offline

    Sagacious_Zed Bukkit Docs

    But you can store a location analog in a hashmap and in turn, Bukkit's Configuration
    Code:java
    1. public final class LocationSerialProxy implements ConfigurationSerializable {
    2.  
    3. private final String world;
    4. private final String uuid;
    5. private final double x;
    6. private final double y;
    7. private final double z;
    8. private final float yaw;
    9. private final float pitch;
    10. private transient Location loc;
    11.  
    12. public LocationSerialProxy(Location l) {
    13. this.world = l.getWorld().getName();
    14. this.uuid = l.getWorld().getUID().toString();
    15. this.x = l.getX();
    16. this.y = l.getY();
    17. this.z = l.getZ();
    18. this.yaw = l.getYaw();
    19. this.pitch = l.getPitch();
    20. }
    21.  
    22. public LocationSerialProxy(Map<String, Object> map) {
    23. this.world = (String) map.get("world");
    24. this.uuid = (String) map.get("uuid");
    25. this.x = (Double) map.get("x");
    26. this.y = (Double) map.get("y");
    27. this.z = (Double) map.get("z");
    28. this.yaw = ((Double) map.get("yaw")).floatValue();
    29. this.pitch = ((Double) map.get("pitch")).floatValue();
    30. }
    31.  
    32. public static LocationSerialProxy deserialize(Map<String, Object> map) {
    33. return new LocationSerialProxy(map);
    34. }
    35.  
    36. public final Map<String, Object> serialize() {
    37. Map<String, Object> map = new HashMap<String, Object>();
    38. map.put("world", this.world);
    39. map.put("uuid", this.uuid);
    40. map.put("x", this.x);
    41. map.put("y", this.y);
    42. map.put("z", this.z);
    43. map.put("yaw", this.yaw);
    44. map.put("pitch", this.pitch);
    45. return map;
    46. }
    47.  
    48. public final Location getLocation(Server server) {
    49. if (loc == null) {
    50. loc = new Location(server.getWorld(this.world), x, y, z, yaw, pitch);
    51. }
    52. return loc;
    53. }
     
  6. Offline

    thehutch

  7. Offline

    halley

    I think you misunderstand what it means to be a key in a hash. You want to capture the unique, the unchanging, the easily distinguished aspects of the data. Location isn't a good key component because very similar sub-block floating-point locations don't compare as equal. Maybe you only need the integer block locations, and not the sub-block floating-point locations. Block types change over time as people make and break their buildings.

    Why are you using Block as a key?

    If you really think you're on the right track, then make a custom class, which implements Serializable and maybe getHash(), and contains nothing but the features you need. Use that as your key.

    Code:
    class MyBlockInfo
        implements Serializable
    {
        private static final long serialVersionUID = 75266236872922776147L;
        int typeid;
        String world;
        int blockx;
        int blocky;
        int blockz;
        public MyBlockInfo() { ; }
        public MyBlockInfo(Block block)
        {
            typeid = block.getTypeId();
            Location loc = block.getLocation();
            world = loc.getWorld();
            blockx = loc.getBlockX();
            blocky = loc.getBlockY();
            blockz = loc.getBlockZ();
        }
    }
    
    D'oh, ninja'd by Zed. I still don't like the idea of storing the floating-point stuff as a component of a unique hash key, though.
     
  8. Offline

    Evenprime

    Block can't implement Serializable because it contains a Location object, which in turn contains a reference to a World object. And it should be quite obvious why you can't serialize a World object.

    So you'll definitely have to do what Sagacious_Zed proposed: Break unserializable objects down into primitive dataTypes and Strings and serializable objects, then when deserializing reassemble them to something that is at least similar to the original.
     
  9. Offline

    Baummann

    I'll try that tomorrow.
     
  10. Offline

    notrub

    @Sagacious_Zed
    That bit of code was exactly the help I needed. Thanx!
     
Thread Status:
Not open for further replies.

Share This Page