文档章节

Java简单字符串插值实现

canghailan
 canghailan
发布于 2012/09/27 17:11
字数 622
阅读 390
收藏 1

字符串插值是非常有用的功能,可以提高编码效率。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;
			}
		}

	}
}

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

 

 

© 著作权归作者所有

canghailan

canghailan

粉丝 28
博文 14
码字总数 10765
作品 0
武汉
程序员
私信 提问
Android Gradle(三)Groovy快速入门指南

本文首发于微信公众号「刘望舒」 原文链接:Groovy快速入门看这篇就够了 前言 在前面我们学习了为什么现在要用Gradle?和Gradle入门前奏两篇文章,对Gradle也有了大概的了解,这篇文章我们接...

刘望舒
2018/10/10
0
0
groovy比起java,有哪些地方写起来更舒服

java发展缓慢,语法落后冗余 说起java,其实java挺好的,java现在的性能也不错,但是,java的语法显然比较落后,而且冗余,getter/setter之类的,5的泛型 for each,autobox,7的钻石语法,try catch 多...

李嘉图
2017/08/31
0
5
为 Java 开发者解读 Groovy 编程风格和语言特性

当一个Java开发人员加入到Groovy的开发之旅的时候,他/她经常带着Java思想去思考,并逐步地学习Groovy,每次学习一个特性,这会让他慢慢变得更有创造性和写出更符合语言习惯的Groovy代码。这...

oschina
2013/01/14
5.9K
18
Scala2.10新特性之 String Interpolation

String Interpolation http://docs.scala-lang.org/overviews/core/string-interpolation.html 2013-1-7 (英语四级未过,借助各种词典、翻译,历时两个晚上,终于翻译完了,如有翻译错误或用...

Ellipse
2013/01/06
0
16
jk3d的使用方法详解——克里金插值的java实现

关于克里金的资料我这里就不罗嗦了,反正这种插值算法是非常优秀的,插值结果可靠度高,最近也是一个问题需要使用插值来解决,首选克里金,但是我大概了解克里金是怎么一回事儿,但要是自己去...

土匪强
2013/01/07
0
5

没有更多内容

加载失败,请刷新页面

加载更多

Linux使用源码包安装软件

前言: 最近整理一些以前的学习笔记。 过去都是存储在本地,此次传到网络留待备用。 源码包 Linux软件多数免费、开源,是开发人员编写的,具有很强可读性的一组相关代码文本。 源码包 --> 编...

迷失De挣扎
今天
3
0
IPv4如何转换为IPv6?

ipv6已经逐渐在应用,现在已经有很多的运营商支持ipv6,前天我们也发布了如何让电脑使用ipv6地址?有很多朋友在问?ipv6有什么作用,它的表示方式是什么,今天我们来一起来详细了解下ipv6相关计...

xiangyunyan
今天
4
0
小白讲网络安全系列

注入攻击防护 XSS注入 SQL注入 命令注入 文件上传 文件解压缩 CSRF防护 对称加密 非对称加密 数字证书 数字签名 完整性校验 消息验证码 单向散列Hash函数 口令单向加密算法 审计日志 认证鉴权...

一刀
今天
2
0
MYSQL 嵌套事务(SAVEPOINT) 与Spring 事务传播

摘要 savepoint 关键字可以实现嵌套事务。结合savepoint关键字,更方便理解spring的事务传播。 事务嵌套 初始化表脚本 drop table t;create table t(a int, primary key(a)); 开启事务 my...

liangxiao
今天
4
0
Chrome OS 更新新版本可让Linux访问USB连接的Android设备

谷歌再次为Chrome OS带来了重大版本更新,使版本号达到了75。本次更新的一大亮点就是允许在Chrome OS上运行的Linux能够识别通过USB方式连接的Android设备,能够让用户使用Linux进行调试等等。...

linuxCool
昨天
20
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部