您的位置:首页 > 编程语言 > Java开发

Java简单字符串插值实现

2012-09-27 17:11 4055 查看

字符串插值是非常有用的功能,可以提高编码效率。Java语言没有提供原生的字符串插值功能,但在标准库中 MessageFormat 提供了部分功能。现在把积累的相关代码整理重构一下,以便以后使用。

例子:

import static java.lang.System.out;
import static cc.interpolation.Interpolations.indexed;
import static cc.interpolation.Interpolations.named;

import java.util.Collections;

public class Test {
public static void main(String[] args) {
out.println(indexed("{0} and {1}", "Li Lei", "Han Meimei"));
out.println(named("{a} and {b}", "a", "Li Lei", "b", "Han Meimei"));
out.println(named("{a} and {unknown}", "a", "A", "default"));
out.println(named("{a} and {unknown}",
Collections.singletonMap("a", "A"), "default"));
}
}

输出:

Li Lei and Han Meimei
Li Lei and Han Meimei
A and default
A and default

 

具体实现如下:

import java.util.Map;

public class Interpolations {
private static final InterpolationEngine INDEXED_ENGINE = new IndexedInterpolationEngine();
private static final InterpolationEngine NAMED_ENGINE = new NamedInterpolationEngine();

public static String indexed(String template, Object... bindings) {
return INDEXED_ENGINE.combine(template,
IndexedInterpolationEngine.createBindings(bindings));
}

public static String named(String template, Object... bindings) {
return NAMED_ENGINE.combine(template,
NamedInterpolationEngine.createBindings(bindings));
}

public static String named(String template, Map<String, ?> bindings) {
return named(template, bindings, null);
}

public static String named(String template, Map<String, ?> bindings,
Object defaultValue) {
return NAMED_ENGINE.combine(template, NamedInterpolationEngine
.createBindings(bindings, defaultValue));
}
}

插值引擎接口:

public interface InterpolationEngine {
public interface Bindings {
Object get(String name);
}

String combine(String template, Bindings bindings);
}

根据主要用到了两种插值方式:索引、命名。

这两种方式都可以使用正则表达式实现。基本的正则表达式插值代码为:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class PatternInterpolationEngine implements InterpolationEngine {
private final Pattern pattern;

public PatternInterpolationEngine(Pattern pattern) {
this.pattern = pattern;
}

@Override
public String combine(String template, Bindings bindings) {
StringBuffer buffer = new StringBuffer(template.length());
Matcher matcher = pattern.matcher(template);
while (matcher.find()) {
String name = matcher.group(1);
Object value = bindings.get(name);
matcher.appendReplacement(buffer, String.valueOf(value));
}
matcher.appendTail(buffer);
return buffer.toString();
}
}

索引方式:

import java.util.regex.Pattern;

public class IndexedInterpolationEngine extends PatternInterpolationEngine {
private static final Pattern PATTERN = Pattern.compile("\\{([0-9]+)\\}");

public IndexedInterpolationEngine() {
super(PATTERN);
}

public static Bindings createBindings(Object... array) {
return new ArrayBindings(array);
}

private static final class ArrayBindings implements Bindings {
private final Object[] array;

public ArrayBindings(Object[] array) {
this.array = array;
}

@Override
public Object get(String name) {
return array[Integer.parseInt(name)];
}
}
}

命名方式:

import java.util.Map;
import java.util.regex.Pattern;

public class NamedInterpolationEngine extends PatternInterpolationEngine {
private static final Pattern PATTERN = Pattern
.compile("\\{([_a-zA-Z0-9]+)\\}");

public NamedInterpolationEngine() {
super(PATTERN);
}

public static Bindings createBindings(Object... array) {
return new AssociativeArrayBindings(array);
}

public static Bindings createBindings(Map<String, ?> map,
Object defaultValue) {
return new MapBindings(map, defaultValue);
}

private static final class AssociativeArrayBindings implements Bindings {
private final Object[] associativeArray;
private final int lookupLength;
private final Object defaultValue;

public AssociativeArrayBindings(Object[] associativeArray) {
this.associativeArray = associativeArray;
if (associativeArray.length % 2 == 0) {
lookupLength = associativeArray.length;
defaultValue = null;
} else {
lookupLength = associativeArray.length - 1;
defaultValue = associativeArray[associativeArray.length - 1];
}
}

@Override
public Object get(String name) {
for (int i = 0; i < lookupLength; i += 2) {
if (name.equals(associativeArray[i])) {
return associativeArray[i + 1];
}
}
return defaultValue;
}
}

private static final class MapBindings implements Bindings {
private final Map<String, ?> map;
private final Object defaultValue;

public MapBindings(Map<String, ?> map, Object defaultValue) {
this.map = map;
this.defaultValue = defaultValue;
}

@Override
public Object get(String name) {
if (map.containsKey(name)) {
return map.get(name);
} else {
return defaultValue;
}
}

}
}

 目前只实现了基本的功能,但是足以应付我现在的需要。如以后有更多的功能需求,再行扩展。

 

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息