`
Surmounting
  • 浏览: 67943 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

爪哇(Java)自定义的二个字符串高效处理方法,在静寂一个半月之后

阅读更多

以下是测试程序运行结果:

source = a b c d e f g h i j k l m n o p q r s t u v w x y z
字符串中删除字符的方法。
系统函数计算 300000 次用时 1984 ms
自定义方法计算 300000 次用时 344 ms
生成 abcdefghijklmnopqrstuvwxyz 。
---------- ---------- ---------- ----------

字符串按字符分割的方法。
系统函数计算 300000 次用时 1609 ms
自定义方法计算 300000 次用时 281 ms
生成 [Ljava.lang.String;@1010058: [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z] 。
---------- ---------- ---------- ----------

能够数倍超越爪哇(Java)类库(Java5.0和Java6.0)中相关方法的性能,究其原因,是因为类库为通用性,提供的相关方法,都采取了正则表达式参数。虽然编译过的正则表达式很高效,但毕竟无法和字符相等这种单拍操作相提并论。

下面把程序发出来,供大家指出错误、讨论以及参考。

首先是删除字符串中某字符的方法。

/**
 * <b>字符串删除其中某字符</b><br/>
 * 本方法用来移除指定字符串中的指定字符。
 * 在 Java 6.0 以内,删除字符串中的指定字符,需要通过
 * {@link String#replace(CharSequence, CharSequence) replace} 方法,将指定单
 * 字符的字符串,替换成空字符串来实现。而 <code>replace</code> 方法为了追求通用,
 * 使用了正则表达式参数。即便是编译过的正则表达式,其性能也无法与简单的字符相等
 * 判断相提并论。<br/>
 * 本方法不涉及正则表达式,通过 {@link StringBuilder} 来删除原字符串中的目标
 * 字符。是一个简单但高效的方法。<br/>
 * 本方法使用示例如下:
 * <pre>
 * String source = "a b c d e f g h i j k l m n o p q r s t u v w x y z";
 * String removed = StringTool.removeChar(source, ' ');</pre>
 * 此示例中,{@link String} source 为原字符串。String removed 为删除空格后的
 * 结果。
 * @see		String#replace(CharSequence, CharSequence)
 * @see		StringBuilder#deleteCharAt(int)
 * @param 	source	待被处理的字符串,即本方法的“原字符串”
 * @param 	target	需要从原字符串中移除的字符
 * @return		从指定原字符串中移除指定字符后所得的结果字符串
 * @exception	NullPointerException	当传入参数 source 为空时
 */
static public String removeChar(String source, char target)
{
	StringBuilder builder = new StringBuilder(source);
	char[] srcChars = source.toCharArray();
	int accumulation = 0;
	for (int index = -1; ++index != srcChars.length; )
		if (srcChars[index] == target)
			builder.deleteCharAt(index - accumulation++);
	return builder.toString();
}


接下来,是字符串分割的方法。

/**
 * <b>简易字符串分割</b><br/>
 * 本方法用来根据指定字符,将某字符串以此为分割,拆分成多个子字符串。
 * 对于分割字符串功能,在 Java 6.0 以内,都只提供了支持正则表达式的
 * {@link String#split(String) split} 方法。此方法为追求通用,即便是简单的
 * 分割,也会基于正则表达式来进行。即便是编译过的正则表达式,其性能也无法与简单
 * 的字符相等判断相提并论。<br/>
 * 本方法不涉及正则表达式,通过遍历原字符串对应的字符数组来寻找符合分割字符的
 * 字符,然后通过 {@link String#substring(int, int)} 来获取每一个分割字符之间
 * 的子字符串,存入一个 {@link LinkedList} 中。这是一个功能简单但高效的方法。
 * 如果规模比较大,拟考虑先通过一次循环,取得原字符串中分割字符的数量,以此制作
 * 定长的 {@link ArrayList} 。
 * 本方法尤其适用于常见的由半角逗号结合在一起的字符串的分割。<br/>
 * 在编写之初,本方法曾采取将字符串的字符数组分段处理,通过系统字符串复制来形成
 * 一个个子字符串。后经考证,{@link String#substring(int, int)} 是一个很高效的
 * 方法,遂改。效率提高了一倍。
 * 本方法使用示例如下:
 * <pre>
 * String source = "a b c d e f g h i j k l m n o p q r s t u v w x y z";
 * List<String> secs = StringTool.splitSimpleString(source, ' ');</pre>
 * 此示例中,{@link String} source 为原字符串。{@link List} secs 为删除空格后
 * 的结果。
 * @see		String#split(String)
 * @see		String#substring(int, int)
 * @param 	source	待被处理的字符串,即本方法的“原字符串”
 * @param 	gap		分割字符
 * @return		从指定原字符按分割字符拆分成的子字符串列表
 * @exception	NullPointerException	当传入参数 source 为空时
 */
static public List<String> splitSimpleString(String source, char gap)
{
	List<String> result = new LinkedList<String>();
	char[] sourceChars = source.toCharArray();
	String section = null;
	int startIndex = 0;
	for (int index = -1; ++index != sourceChars.length; )
	{
		if (sourceChars[index] != gap) continue;
		section = source.substring(startIndex, index);
		result.add(section);
		startIndex = index + 1;
	}
	section = source.substring(startIndex, sourceChars.length);
	result.add(section);
	return result;
}


最后是测试程序。

static public void main(String[] arguments)
{
	// 准备测试内容
	String source = "a b c d e f g h i j k l m n o p q r s t u v w x y z";
	System.out.println("source = " + source);
	int loop = 300000;
	String resultString = null;
	List<String> resultList = null;
	String[] resultArr = null;
	int index = -1;

	long start = Calendar.getInstance().getTimeInMillis();
	System.out.println("字符串中删除字符的方法。");

	// 测试 Java 类库提供的字符串删除某字符
	index = -1;
	while (++index != loop)
		resultString = source.replace(" ", "");
	long end1 = Calendar.getInstance().getTimeInMillis();
	System.out.println("系统函数计算 " + loop + " 次用时 " + (end1 - start) + "ms");

	// 测试自定义的字符串删除某字符
	index = -1;
	while (++index != loop)
		resultString = StringTool.removeChar(source, ' ');
	long end2 = Calendar.getInstance().getTimeInMillis();
	System.out.println("自定义方法计算 " + loop + " 次用时 " + (end2 - end1) + "ms");

	System.out.println("生成 " + resultString + " 。");
	System.out.println("---------- ---------- ---------- ----------\n");

	// 测试 Java 类库提供的字符串按某字符分割
	System.out.println("字符串按字符分割的方法。");
	index = -1;
	while (++index != loop) resultArr = source.split(" ");
	long end3 = Calendar.getInstance().getTimeInMillis();
	System.out.println("系统函数计算 " + loop + " 次用时 " + (end3 - end2) + "ms");

	// 测试自定义的字符串按某字符分割
	index = -1;
	while (++index != loop)
		resultList = StringTool.splitSimpleString(source, ' ');
	long end4 = Calendar.getInstance().getTimeInMillis();
	System.out.println("自定义方法计算 " + loop + " 次用时 " + (end4 - end3) + "ms");

	System.out.println("生成 " + resultArr + ": " + resultList + " 。");
	System.out.println("---------- ---------- ---------- ----------\n");
}


本文也在我 CSDN 的博客发表: http://blog.csdn.net/shanelooli/article/details/8123094

分享到:
评论
5 楼 Surmounting 2012-11-06  
skzr.org 写道
new StringBuilder可以传入字符串长度这样避免了array扩容。

有效果有效果!
能稳定提高 10% 左右的效率~

太感谢了。没想到在这种情况下还能够继续提高。看来我编程的好习惯还是不足啊。以前只有做 ArrayList 和 HashMap 指定尺寸的习惯,StringBuilder 缺乏这个意识。
4 楼 skzr.org 2012-11-06  
new StringBuilder可以传入字符串长度这样避免了array扩容。
3 楼 Surmounting 2012-11-05  
skzr.org 写道
说实在的,这个处理性能确实不错。
我前年做小说采集器时,也是这样处理的,没有用系统的也是性能+内存的原因。
1. 系统的substring实际上内部的那个数组内存不会被释放的,有潜在的内存泄漏:所以当时采用了new String()
2. string内部用正则,对于一般的查找替换等没必要,直接操作更快

你这个很不错。


以下是改进版:

/**
* <b>字符串删除其中某字符</b><br/>
* 本方法用来移除指定字符串中的指定字符。
* 在 Java 6.0 以内,删除字符串中的指定字符,需要通过
* {@link String#replace(CharSequence, CharSequence) replace} 方法,将指定单
* 字符的字符串,替换成空字符串来实现。而 <code>replace</code> 方法为了追求通用,
* 使用了正则表达式参数。即便是编译过的正则表达式,其性能也无法与简单的字符相等
* 判断相提并论。<br/>
* 本方法不涉及正则表达式,通过遍历原字符串对应的字符数组来寻找符合待删除字符的
* 字符,然后通过 {@link StringBuilder} 来追加其余字符。这是一个简单但高效的方法。
* <br/>
* 本方法编写之初,曾试图通过 <code>StringBuilder</code> 的功能来直接删除字符串
* 中待删除字符。后经 www.iteye.com 网站用户 shenyuc629 提示,并经过考证,发现
* {@link StringBuilder#deleteCharAt(int) deleteCharAt} 方法并不高效,应该是
* 因为其内部每次删除都进行了数组迁移。遂改为追加方式,效率提高了 2 倍多。<br/>>>
* 本方法使用示例如下:
* <pre>
* String source = "a b c d e f g h i j k l m n o p q r s t u v w x y z";
* String removed = StringTool.removeChar(source, ' ');</pre>
* 此示例中,{@link String} source 为原字符串。String removed 为删除空格后的
* 结果。
* @see String#replace(CharSequence, CharSequence)
* @see StringBuilder#append(char)
* @param source 待被处理的字符串,即本方法的“原字符串”
* @param target 需要从原字符串中移除的字符
* @return 从指定原字符串中移除指定字符后所得的结果字符串
* @exception NullPointerException 当传入参数 source 为空时
*/
static public String removeChar(String source, char target)
{
StringBuilder builder = new StringBuilder();
for (char c: source.toCharArray())
if (c != target) builder.append(c);
return builder.toString();
}
2 楼 Surmounting 2012-11-03  
skzr.org 写道
说实在的,这个处理性能确实不错。
我前年做小说采集器时,也是这样处理的,没有用系统的也是性能+内存的原因。
1. 系统的substring实际上内部的那个数组内存不会被释放的,有潜在的内存泄漏:所以当时采用了new String()
2. string内部用正则,对于一般的查找替换等没必要,直接操作更快

你这个很不错。


我这个也没能避免 substring() 的内存泄露问题。明天加班,看看咋改法。
另外对于删除某字符,经 ITeye 的朋友提示,deleteCharAt() 方法会引起即时的数组重写,不如直接用 StringBuilder 一个个 append() 。经测试用新方法速度增加 2-2.5 倍。
1 楼 skzr.org 2012-11-03  
说实在的,这个处理性能确实不错。
我前年做小说采集器时,也是这样处理的,没有用系统的也是性能+内存的原因。
1. 系统的substring实际上内部的那个数组内存不会被释放的,有潜在的内存泄漏:所以当时采用了new String()
2. string内部用正则,对于一般的查找替换等没必要,直接操作更快

你这个很不错。

相关推荐

    java自定义注解\标签库\监听\junit简单测试

    Java自定义注解是Java平台提供的一种元编程机制,它允许程序员在源代码中的任何元素(类、方法、变量等)上添加元数据。自定义注解可以被编译器或者运行时系统用来执行特定的任务,例如代码分析、性能监控、持久化...

    JAVA反射机制自定义框架测试代码

    Java反射机制是Java编程语言中的一个强大工具,它允许运行中的Java程序对自身进行检查并且可以直接操作程序的内部属性。这个特性使得Java具有了高度的灵活性和动态性,尤其是在构建框架和库时尤为有用。本篇文章将...

    javapoet,爪哇语.zip

    JavaPoet是一个强大的开源项目,专门设计用于在Java编程环境中生成.java源代码文件。这个API由Square公司开发,为开发者提供了简洁、优雅的方式来构建和编辑Java源代码,从而简化了元编程任务。以下是对JavaPoet及其...

    爪哇class汉化翻译器

    如果hhclass是一个工具,它可能是专门设计用来打开、编辑和保存.class文件的,允许用户查找和替换其中的字符串。 汉化翻译器的工作原理大致如下: 1. **反编译**:首先,工具会将.class文件反编译成可读的Java源...

    爪哇夜未眠(蔡學鏞java)

    接着,异常处理是Java程序设计中的一个重要环节。Java使用try-catch-finally语句块来捕获和处理运行时错误,确保程序的健壮性。此外,finally块可以确保无论是否发生异常,某些代码都能被执行,如资源的关闭。 多...

    Async Http Client,爪哇.zip

    Async Http Client是一款高效的开源HTTP客户端库,专为Java...对于想要在Java应用中实现高效、灵活的HTTP通信的开发者来说,这是一个非常有价值的资源。同时,参与开源项目也能提升个人的编程能力和对网络协议的理解。

    capnproto-java,纯爪哇船长.zip

    这个“capnproto-java,纯爪哇船长.zip”文件包含的是Cap'n Proto的Java实现,名为“capnproto-java-master”,这是一个开源项目,允许开发者在Java平台上利用Cap'n Proto的优势。 Cap'n Proto的核心特性包括: 1. *...

    爪哇夜未眠.rar

    在高级主题方面,书籍可能涵盖了多线程编程,这是Java的一个强项。读者将学习如何创建和管理线程,理解同步和互斥的概念,以及如何避免常见的并发问题。此外,可能还会涉及Java的IO和NIO系统,这对于处理输入输出...

    java学习教材(java私塾跟我学系列--java篇)

    - **Java命名由来**:Oak项目组在一次咖啡馆会议中决定将新语言命名为Java,这一名称来源于他们在讨论时所喝的爪哇咖啡。 - **Java的现状**:Java自问世以来迅速成为业界热门编程语言之一,被广泛应用于互联网应用...

    Java处理Excel源代码

    在Java编程中,处理Excel文件是一项常见的任务,特别是在数据导入导出、数据分析或者报表生成等场景。本主题主要关注如何使用Java来读取、修改和写入Excel文件。以下是一些核心的知识点: 1. **Apache POI库**:...

    爪哇运行环境Windows

    例如,如果有一个名为`HelloWorld.class`的文件,可以在命令行输入`java HelloWorld`来运行。对于`.jar`文件,可以使用`java -jar yourfile.jar`来启动。 Java虚拟机(JVM)是Java运行环境的核心,它负责解析和执行...

    全国等级考试二级Java复习资料

    - Java的起源可以追溯到上世纪90年代初,当时Sun Microsystems公司启动了一个名为Green的项目,旨在为家用消费电子产品开发一个分布式代码系统,以便能够控制家用电器并与之进行信息交换。 - 该项目由James ...

    Java技术与应用 Java技术与应用.ppt

    Java的另一个显著特点是它的强健性。编译时和运行时的错误检查确保了程序的稳定性和可靠性。Java是一种静态类型的语言,这意味着变量的类型在编译时就已经确定,这有助于防止因类型错误导致的运行时故障。Java还引入...

    javajava课程设计书

    Java的命名来源于印度尼西亚的一个岛屿——爪哇岛,意在象征着为用户带来如同咖啡般的清新体验。 #### 二、Java的组成部分 1. **Java语言**:一种面向对象的编程语言,支持多种操作系统和设备上的应用开发。 2. **...

    Java语言简介+JDK安装+配置+第一个程序HelloWorld编译运行

    Java 语言简介、JDK 安装和配置、第一个程序 HelloWorld 编译运行 Java 语言简介 Java是一种面向对象的程序设计语言,由Sun公司开发,主要是基于安全性和高效考虑。Java 不仅是一种语言,也是一种技术。它的原意...

    java入门思维导图

    Java语言其实是有个曾用名的~叫Oak,而且起这个名字...最后他们以Java这个名字命名了这个语言,据说是Sun公司的程序猿们都很喜欢喝咖啡,而且对爪哇岛的一种咖啡印象很深,所以就有了Java这个经典的名字和咖啡的图标。

    Java基础课程大纲.pdf

    Java中允许一个类继承一个父类或实现多个接口,以此来扩展类的功能。 以上内容是Java基础课程的主要知识点,涵盖了Java语言的历史背景、特性、体系结构、基本语法、数据类型、命名规则、注释以及继承和接口等方面的...

    jAVA无难事课件整理.ppt

    总之,Java凭借其简单性、面向对象、健壮性、安全性、跨平台和多线程等特性,成为了一个深受开发者喜爱的编程语言。无论你是初学者还是经验丰富的程序员,深入理解和掌握Java都将对你的职业生涯大有裨益。

    Java课件第一章java概述课件

    Java 的名称来源于两种说法:一是源自印度尼西亚的爪哇岛,寓意提供一种如同咖啡般提神醒脑的力量;二是源于美国俚语,象征着活力和热情。 Java 的特性包括: 1. **面向对象**:Java 强调面向对象编程,允许程序员...

    Java全部PPT课件.ppt

    Java语法基础包括了解Java语言的基本语法结构,包括变量、数据类型、运算符、控制结构、方法、数组和字符串等。Java语法基础还包括了解Java语言的面向对象编程特性,如类、对象、继承和多态等。 Java面向对象的编程...

Global site tag (gtag.js) - Google Analytics