简体   繁体   中英

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.

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=}

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

It's quite trivial to roll your own:

// assumes that input is properly formed e.g. "k1=v1,k2=v2"
public Map<String, String> toMap(String input) {
    Map<String, String> map = new HashMap<String, String>();
    String[] array = input.split(",");
    for (String str : array) {
        String[] pair = str.split("=");
        map.put(pair[0], pair[1]);
    }
    return map;
}

Not in guava.

But StringToMap can do this for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM