Tuesday, July 27, 2010

Generic Conversion Between List<T> and String

Here's a reusable generic "converter" interface for converting between comma-separated strings and Lists of a given type:

/**
* Converts between comma-separated string and lists of type T.
*/
public abstract class AbstractConverter<T> {

protected abstract T getInstance(String s);

/**
* Converts a list of items into a comma-separated string
*/
public String toString(List<T> items)
{
String s= "";
String comma = "";
for (T item : items) {
s += comma + item;
comma = ",";
}
return s;
}

/**
* Converts a comma-separated string into a list of items.
*/
public List<T> toList(String csv)
{
if (csv == null)
{
return new ArrayList<T>();
}

String[] items = csv.split(",");
List<T> theList = new ArrayList<T>();
for (String item : items) {
T thisItem = getInstance(item);
theList.add(thisItem);
}
return theList;
}

/**
* Converts a comma-separated string into a list of items, excluding any items in the given
* exclude list.
*/
public List<T> toList(String csv, List<T> excludes)
{
if (csv == null)
{
return new ArrayList<T>();
}

String[] items = csv.split(",");
List<T> theList = new ArrayList();
for (String item : items) {
T thisItem = getInstance(item);
if (!excludes.contains(thisItem))
{
theList.add(thisItem);
}
}
return theList;
}
}

I can now provide concrete converter classes of types as needed, for example:

/**
* Converts between comma-separated string and lists of MyType objects.
*/
public class MyConverter extends AbstractConverter<MyType> {

// provide an instance of the custom type
protected MyType getInstance(String s)
{
return new MyType(s);
}

// optionally enforce a singleton, if needed
private MyConverter() {
// EMPTY
}

// provide a convenience for static utility classes
private static AbstractConverter<MyType> cvt = new MyConverter();
public static AbstractConverter<MyType> inst()
{
return cvt;
}
}

Since I want to make things convenient for clients of this, I now provide a static utility class that precludes the need to instantiate anything:

public class MyHelper {

private static AbstractConverter cvt = MyConverter.inst();

public static String toString(List<MyType> items)
{
return cvt.toString(items);
}

public static List<MyType> toList(String csv)
{
return cvt.toList(csv);
}

public static List<MyType> toList(String csv, List<MyType> excludes)
{
return cvt.toList(csv, excludes);
}
}

Now my clients can call e.g. MyHelper.toList("x, y, z") instead of MyConverter.inst().toList("x, y, z"). A small advantage, but it does help with readability and reinforces the notion that this is a collection of utility functions.

No comments:

Post a Comment