是否可以在不复制 Set 的情况下序列化 Map.keySet?

Is it possible to serialize Map.keySet without copying the Set?

众所周知,Map的KeySet是不可序列化的。但在某些情况下,我只想通过线路发送包裹在自定义对象中的 Map 的 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);
    }
}

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

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();
}