是否可以序列化Map.keySet而无需复制Set?

时间:2015-06-07 06:49:55

标签: java serialization

众所周知,Map的KeySet不可序列化。但我有一些情况,我只想通过网络发送包裹在自定义对象中的地图的KeySet。所以我已经实现了writeObject方法来检查可序列化的Set。

我现在的问题是,如果有办法获得二进制表示而不将整个Set复制到一个新的Set中?这对我来说效率非常低,因为在这种情况下我们通常有大量的地图(这是我们发送密钥而不是整个地图的原因之一)。

public class Serialize2 implements Serializable {
    private static final Class TM_KS_CLASS = new TreeMap<>().keySet().getClass();
    private static final Class LM_KS_CLASS = new LinkedHashMap<>().keySet().getClass();

    private Set<String> testSet;
    public String justSomeOtherFieldToSerialize;

    public Serialize2(Set<String> testSet) {
        this.testSet = testSet;
    }

    public Set<String> getTestSet() {
        return testSet;
    }

    private void writeObject(java.io.ObjectOutputStream stream) throws java.io.IOException {
        if (!(testSet instanceof Serializable)) {
            if (testSet.getClass().equals(TM_KS_CLASS)) {
                testSet = new TreeSet<>(testSet);
            } else {
                testSet = new HashSet<>(testSet);
            }
        }

        stream.defaultWriteObject();
    }

    @Override
    public String toString() {
        return "Serialize2{" +
                "testSet=" + testSet +
                '}';
    }

    public static void main(String[] args) {
        Map<String, Integer> foo = new HashMap<>();
        foo.put("lala", 1);
        foo.put("lolo", 2);
        foo.put("lulu", 3);
        foo.put("lili", 4);

        Serialize2 sTest = new Serialize2(foo.keySet());
        Serialize2 dsTest = (Serialize2) SerializationUtils.deserialize(SerializationUtils.serialize(sTest));
        System.out.println(dsTest);
    }
}

1 个答案:

答案 0 :(得分:1)

是的,一种方法是单独序列化每个对象而不复制到新的集合中,

private void writeObject(java.io.ObjectOutputStream stream) throws java.io.IOException {
    Iterator itr = testSet.iterator();
    if (testSet.getClass().equals(TM_KS_CLASS)) {
        stream.writeBoolean(true);
    } else {
        stream.writeBoolean(false);
    }
    stream.writeInt(testSet.size());
    while(itr.hasNext()) {
        stream.writeObject(itr.next());
    }
    stream.writeObject(justSomeOtherFieldToSerialize);
}

您需要具有相应的readObject实现,该实现分别读取每个对象并放入一个集合,例如

private void readObject(java.io.ObjectInputStream stream) throws java.io.IOException {
    boolean bTypeofmap = stream.readBoolean(); // Whether its a TreeMap or LinkedhashMap
    int size = stream.readInt();
    testSet = new java.util.HashSet(size);
    for(int i = 0; i < size; i++) {
        testSet.add(stream.readObject());
    }
    justSomeOtherFieldToSerialize = (String) stream.readObject();
}