From a178086dfa3c17a06465bcd39195fb741a506187 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Thu, 28 Sep 2017 19:02:43 +0200 Subject: [PATCH] make IntList serializable --- .../java/org/lucares/collections/IntList.java | 54 +++++++++++++++++-- .../org/lucares/collections/IntListTest.java | 42 +++++++++++++++ 2 files changed, 93 insertions(+), 3 deletions(-) diff --git a/primitiveCollections/src/main/java/org/lucares/collections/IntList.java b/primitiveCollections/src/main/java/org/lucares/collections/IntList.java index e6dc760..65c5e40 100644 --- a/primitiveCollections/src/main/java/org/lucares/collections/IntList.java +++ b/primitiveCollections/src/main/java/org/lucares/collections/IntList.java @@ -1,5 +1,6 @@ package org.lucares.collections; +import java.io.Serializable; import java.util.Arrays; import java.util.List; @@ -9,7 +10,7 @@ import java.util.List; * This class does not (yet) implements all methods a java.util {@link List} * would have. */ -public class IntList { +public class IntList implements Serializable { // TODO make Serializable // TODO make Cloneable @@ -27,6 +28,8 @@ public class IntList { // TODO add toArray(int[] a) // TODO remove bounds checks that are handled by java, e.g. negative indices + private static final long serialVersionUID = 2588449582065895141L; + private static final int DEFAULT_CAPACITY = 10; /** @@ -36,7 +39,11 @@ public class IntList { private static final int[] EMPTY_ARRAY = {}; - private int[] data; + /** + * The array containing the values. It is transient, so that we can implement + * our own serialization. + */ + transient private int[] data; private int index = 0; @@ -96,7 +103,7 @@ public class IntList { /** * Returns the number of elements this list can hold before a resize is - * necessary. + * necessary, this is the size of the internal backing array. * * @return the number of elements this list can hold before a resize is * necessary @@ -351,4 +358,45 @@ public class IntList { return true; } + + /** + * Serialize the {@link IntList}. + *

+ * This only serializes the used part of the data array. + * + * @serialData The length of the array containing the values, followed by the + * values. + */ + private void writeObject(final java.io.ObjectOutputStream s) throws java.io.IOException { + s.defaultWriteObject(); + + // write out the array length. According to the implementation in ArrayList this + // is needed to be compatible with clone. + s.writeInt(index); + + for (int i = 0; i < index; i++) { + s.writeInt(data[i]); + } + } + + /** + * Deserialize the {@link IntList} + */ + private void readObject(final java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { + data = EMPTY_ARRAY; + + s.defaultReadObject(); + + // Read in capacity + s.readInt(); // ignored + + if (index > 0) { + final int[] local_data = new int[index]; + + for (int i = 0; i < index; i++) { + local_data[i] = s.readInt(); + } + data = local_data; + } + } } diff --git a/primitiveCollections/src/test/java/org/lucares/collections/IntListTest.java b/primitiveCollections/src/test/java/org/lucares/collections/IntListTest.java index e7b3290..40fe282 100644 --- a/primitiveCollections/src/test/java/org/lucares/collections/IntListTest.java +++ b/primitiveCollections/src/test/java/org/lucares/collections/IntListTest.java @@ -1,5 +1,10 @@ package org.lucares.collections; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.util.Arrays; import java.util.List; import java.util.concurrent.ThreadLocalRandom; @@ -413,4 +418,41 @@ public class IntListTest { return result; } + + @Test + public void testSerialize() throws IOException, ClassNotFoundException { + final IntList emptyList = new IntList(0); + internalSerializeTest(emptyList); + + final IntList emptyListWithCapacity = new IntList(10); + internalSerializeTest(emptyListWithCapacity); + + final IntList threeElements = new IntList(10000); + threeElements.addAll(1, 2, 3); + internalSerializeTest(threeElements); + + final IntList trimmedList = new IntList(10000); + trimmedList.addAll(1, 2, 3); + trimmedList.trim(); + internalSerializeTest(trimmedList); + } + + private void internalSerializeTest(final IntList list) throws IOException, ClassNotFoundException { + final ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream(); + try (final ObjectOutputStream out = new ObjectOutputStream(byteBuffer)) { + out.writeObject(list); + } + + try (ByteArrayInputStream byteInputStream = new ByteArrayInputStream(byteBuffer.toByteArray()); + ObjectInputStream in = new ObjectInputStream(byteInputStream)) { + final IntList actual = (IntList) in.readObject(); + + Assert.assertEquals(list, actual); + + Assert.assertEquals( + "The capacity of the deserialized list. Should be equal to the number of inserted " + + "values, because we don't want to serialize the unused part of the array", + list.size(), actual.getCapacity()); + } + } }