This works for me:
class StreamToInflateStringToMap {
private static Function<String, String> keyMapper =
s -> s.substring(0, s.indexOf(":"));
private static Function<String, String> valueMapper =
s -> s.substring(s.indexOf(":") + 1);
public static Map<String, String> inflateStringToMap(String flatString) {
return Stream.of(flatString.split(";")).
collect(Collectors.toMap(keyMapper, valueMapper));
}
public static void main(String[] args) {
String flatString = "type:fruit;color:yellow;age:5";
System.out.println("Flat String:\n" + flatString);
Map<String, String> inflatedMap = inflateStringToMap(flatString);
System.out.println("Inflated Map:\n" + inflatedMap);
}
}
Note that I've assumed that you meant that you wanted a solution for when the semicolon was missing (that is: there is only one item in the Map). If there is no colon then it is entirely right that an exception be thrown, because it means that there is no mapping defined in the string and a bad value must have been passed to the method.
The comment put forward by Alexey Romanov is also valid: can you guarantee that the delimiter characters will not be found within the content as part of the actual key/value Strings? If not then you'll hit trouble (whatever method of inflating you use) so it's probably necessary to validate the values being put into the original copy of the Map.
Also note that I've declared the Function<String, String> mappers as static members of the class, but you could shoehorn them directly into the Stream flow if you never need to use them anywhere else and you don't think it makes the code too ugly.
Additionally, some hunting through the Java 8 API has uncovered an alternative way to create a Stream from a delimiter-separated String. You can use the Pattern.splitAsStream(CharSequence) method, something like this:
private static final Pattern SINGLE_SEMICOLON = Pattern.compile(";");
public static Map<String, String> inflateStringToMap(String flatString) {
return SINGLE_SEMICOLON.splitAsStream(flatString).
collect(Collectors.toMap(keyMapper, valueMapper));
}
(Note the warning in the API about feeding mutable CharSequence types such as StringBuilder to the splitAsStream method.)
;or:inside the value?