Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is there a string to map splitter in google collections

I am looking for the opposite of map joiner in google collections. is there something like this, and if not why?

EDIT: here is an example how I wish it would be:

Map<String,String> myMap = Splitter.on(",").keyValueSeparator("=").split("k1=v1,k2=v2");

EDIT: I opened a request and it was implemented. will be available in guava R10.

like image 575
oshai Avatar asked Nov 04 '10 09:11

oshai


2 Answers

Here's a class Maps2 that provides a method

Map<String, String> mapSequence(String)

It also provides two overloaded methods where you can change the delimiters that are used a) between keys and values (default: =) and b) between entries (default: ,). Guava classes like Splitter and Iterables are used internally to do the work. The returned map is a LinkedHashMap, so entry order is preserved.

public final class Maps2{

    public static final String DEFAULT_ENTRY_DELIMITER = ",";
    public static final String DEFAULT_KEYVALUE_DELIMITER = "=";

    private Maps2(){}

    public static Map<String, String> mapSequence(final String sequence){
        return mapSequence(sequence, DEFAULT_KEYVALUE_DELIMITER);
    }

    public static Map<String, String> mapSequence(final String sequence,
        final String keyValueDelim){
        return mapSequence(sequence, keyValueDelim, DEFAULT_ENTRY_DELIMITER);
    }

    public static Map<String, String> mapSequence(final String sequence,
        final String keyValueDelim, final String entryDelim){

        final Splitter entrySplitter =    Splitter.on(entryDelim)
                                                  .trimResults();
        final Splitter keyValueSplitter = Splitter.on(keyValueDelim)
                                                  .trimResults();
        final Map<String, String> map = Maps.newLinkedHashMap();
        for(final String token : entrySplitter.split(sequence)){
            final String[] items =
                Iterables.newArray(
                    keyValueSplitter.split(token), String.class);
            if(items.length != 2){
                throw new IllegalArgumentException(
                   "Map String not well-formed");
            }
            map.put(items[0], items[1]);
        }
        return map;
    }

}

Test code:

public static void main(final String[] args){
    // note the randomly spread whitespace in the test code,
    // also the last entry has no value.
    // using Splitter().trimResults() we can handle junk like that
    final Map<String, String> map = Maps2.mapSequence("k1=v1 ,k2=v2, k3 =");
    System.out.println(map);
}

Output:

{k1=v1, k2=v2, k3=}

like image 182
Sean Patrick Floyd Avatar answered Oct 16 '22 11:10

Sean Patrick Floyd


I think there no such a feature in guava. For me the reason is that the entry String can have many formats, so that you have to create your own "parser" for your own format. An (ugly) alternative could be this one, if you can modify the format of your entry string:

final String toSplit = "k1=v1" + getProperty("line.separator") + "k2=v2";
final Properties properties = new Properties();
properties.load(new ByteArrayInputStream(toSplit.getBytes(Charsets.UTF_8)));
Maps.fromProperties(properties);
like image 2
sly7_7 Avatar answered Oct 16 '22 12:10

sly7_7