patternjavaMinor
A tiny library for textual serialization of lists in Java
Viewed 0 times
serializationtextualjavatinyforlibrarylists
Problem
Note: see the next iteration.
I have this tiny library for (de)serializing lists of objects. The requirement is that each object's state may be represented textually as a single line of text. Later on, the deserialization routine attempts to map each text line to the object it encodes.
Factory.java:
```
package net.coderodde.lists.serial;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/**
* This class holds the methods for serializing/deserializng the lists. The
* convention used here is that every object can be serialized to a single line
* describing the state of that object. Upon deserialization, each row should
* gracefully produce the object with its recorded state. For instance, the
* format of comma-separated values (CSV) resembles this very well.
*
* @author Rodion "rodde" Efremov
* @version 1.6
*/
public class Factory {
/**
* Serializes the all the elements. Each element should serialize to a
* single line, as the deserialization routine assumes that each line
* represents the state of exactly one element.
*
* @param the actual element type.
* @param list the list of elements to serialize.
* @param serializer the element serializer.
* @return the string representation of the entire list.
*/
public static String serialize(List list,
LineSerializer serializer) {
StringBuilder sb = new StringBuilder();
list.stream().forEach((element) -> {
sb.append(serializer.serialize(element)).append("\n");
});
return sb.toString();
}
/**
* Deserializes the entire text text to the list of elements
* being encoded. This routine assumes that each line describes a single
* element.
*
* @param the actual element type.
* @param text the text to deserialize.
* @param deserializer the deserialization object.
I have this tiny library for (de)serializing lists of objects. The requirement is that each object's state may be represented textually as a single line of text. Later on, the deserialization routine attempts to map each text line to the object it encodes.
Factory.java:
```
package net.coderodde.lists.serial;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/**
* This class holds the methods for serializing/deserializng the lists. The
* convention used here is that every object can be serialized to a single line
* describing the state of that object. Upon deserialization, each row should
* gracefully produce the object with its recorded state. For instance, the
* format of comma-separated values (CSV) resembles this very well.
*
* @author Rodion "rodde" Efremov
* @version 1.6
*/
public class Factory {
/**
* Serializes the all the elements. Each element should serialize to a
* single line, as the deserialization routine assumes that each line
* represents the state of exactly one element.
*
* @param the actual element type.
* @param list the list of elements to serialize.
* @param serializer the element serializer.
* @return the string representation of the entire list.
*/
public static String serialize(List list,
LineSerializer serializer) {
StringBuilder sb = new StringBuilder();
list.stream().forEach((element) -> {
sb.append(serializer.serialize(element)).append("\n");
});
return sb.toString();
}
/**
* Deserializes the entire text text to the list of elements
* being encoded. This routine assumes that each line describes a single
* element.
*
* @param the actual element type.
* @param text the text to deserialize.
* @param deserializer the deserialization object.
Solution
Factory is a terrible name for a class. What does it make? As best as I can tell, it doesn't make anything, it just de/serializes. Honestly, I don't think you even need it; you could easily put (de)serialize in the respective classes. LineSerializer and LineDeserializer operate on Strings, which may very well contain newlines or carriage returns or both. It'd recommend renaming them to StringSerializer and StringDeserializer, respectively. In
serialize:list.stream().forEach((element) -> {
sb.append(serializer.serialize(element)).append("\n");
});Why are you making a stream just to iterate over a
List? Use an advanced for (for (a : b)):for (E element : list) {
sb.append(serializer.serialize(element)).append("\n");
}Streams are designed to be used when you have to do lots of fancy stuff, like filter, map, and all that good stuff. Building one just to iterate over things is kinda a waste. Sure, it works, and it's fancy, but you may as well use the old methods.Your method documentation is mostly good, and very complete. I like it. Keep it up. You should continue documenting even in the methods, however -- whenever you make an unintuitive choice, leave a note explaining why.
public static void main(final String... args) {
// ...
}You know, I've never seen it written like this. It's always been
String[] args, rather than final String... args. Functionally, they're the same, but just thought I'd point out that the convention seems to be an array, not varargs.One big issue though: What if people want to have newlines in their object definitions? It'd be more extensible to take a
List and iterate over that, then maybe provide an overloaded method that takes a String and splits it along platform-specific newlines and calls the normal method on the resulting List. In pseudocode that looks awfully like Ruby:def serialize(list_of_strings, serializer)
return list_of_strings.map { |string| serializer.serialize(string) }
end
def serialize(string, serializer)
return serialize(string.split(/\r?\n/), serializer)
endYou know, rereading the Ruby, I just realized that if you chose to use
List/Lists, it's a lot simpler: Just use Collection#Stream, Stream#map, and Stream#toArray(IntFunction<A[]<). If you'd like an example of what I mean, I'd be happy to type up what I mean. It's a little confusing to use.Code Snippets
list.stream().forEach((element) -> {
sb.append(serializer.serialize(element)).append("\n");
});for (E element : list) {
sb.append(serializer.serialize(element)).append("\n");
}public static void main(final String... args) {
// ...
}def serialize(list_of_strings, serializer)
return list_of_strings.map { |string| serializer.serialize(string) }
end
def serialize(string, serializer)
return serialize(string.split(/\r?\n/), serializer)
endContext
StackExchange Code Review Q#94115, answer score: 8
Revisions (0)
No revisions yet.