`
ahuaxuan
  • 浏览: 639508 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

过滤字符的性能调优?挤一挤还是有的

阅读更多

/*

  *author: ahuaxuan(张荣华)

  *date: 2010-05-28

  */

 

 

起因

       前一段时间和其他系统集成, 另外一个系统对某个参数有一个限制,需要将字符串中的特殊字符过滤掉, 由于需要过滤的字符是对方定义的, 所以对方直接把他们系统中的过滤的代码给我了, 代码如下:

 

private String escape(String s) {
        if (s == null) {
            return null;
        }

		StringBuilder sb = new StringBuilder(s.length());

      
		for (int i = 0; i < s.length(); i++) {
			char c = s.charAt(i);
          
            if (c == '\\' || c == '+' || c == '-' || c == '!' || c == '('
					|| c == ')' || c == '^' || c == '[' || c == ']' || c == ':'
					|| c == '{' || c == '}' || c == '~' || c == '*' || c == '?'
					|| c == '|' || c == '&' || c == '>' || c == '<') {
				sb.append(“ ”);
			} else {
                sb.append(c);
            }

		}

		return sb.toString();
	}
 

拿到代码之后, ahuaxuan没有作过多的思考, 而是直接把这段代码贴到自己的代码中, 事实证明它运行”良好”.今天重新审视这段代码的时候,发现还是有改进的余地.

 

分析

特征分析, 上面这段代码的主要作用是将字符串中出现的固定字符替换成空格, 这些需要替换的字符也是我们常见的字符.

面对这样一个需求, 有的程序员会想到replace方法,有的程序员会想到上面的多次||的方法(但是多次||的问题在于如果你的字符不是需要过滤的字符,那么程序就一直会执行到最后一个||,这绝对性能上的浪费阿), 也有的程序员会想到hash的方式. 其实我们的最终目的其实就是: 

给定一个字符, 你怎么判断这个字符是否在某个常见的字符列表中.

 

你肯定不想用迭代, 你也肯定不想用if else if, 你可能比较喜欢用hash, 但是注意这里的”常见字符”这几个字. 

 

是因为它们在ascii 码里所以它们才常见, 还是因为他们常见,所以放到ascii 码里呢, 但不管怎么样, 事实上它们确实是在ascii码里, 也就是说他们之中最大的都不会超过255.

 

所以这个时候, 我们的方案就浮出水面了, 由于我们只要检查每个char是否==这些常见的char就行了. 说到这里, 你是不是又想起了if else if, 这个只是思维的惯性, 如果你再把这些char想像成一个个数字呢.

 

本质和方案

于是需求就转换成了---在个数字段中, 找到某些我们预先定义的需要过滤的数字, 并将起替换成空格,而我们定义的数字都是小于255的.

 

在这样一个需求中, 最快的方式是啥咧, 数组是不, 比如说我们定义的需要过滤的数字是[2, 5], 我们的数字序列是1 2 3 4 5 10 11 110......

那么我们只要遍历这个数字, 然后判断这个数字在我们的过滤数组中是否存在. 我们的过滤数组怎么组织呢?

filterchars = [0, 0, 1, 0, 0, 1], 

 

 

然后我们只需要判断filterchars[k] > 1就知道是个字符是否是需要过滤的字符了(当然这里要注意数组越界了).


代码如下:
public int[] dic = new int[256];
    private String filterChars = "\\+-!()^[]:{}~*?|&><";

    /**
 * User: ahuaxuan
 * Date: 2010-5-28
 * Time: 13:17:11
 */
    public CharFilter() {
        for (int k = 0; k < filterChars.length(); k++) {
            //这里浪费了一些byte.
            char c = filterChars.charAt(k);
            if (c < 256) {
                dic[c] = 1;
            }
        }
    }


    public String newEscape(String abc) {
        if (abc == null) {
            return null;
        }

        StringBuilder rs = new StringBuilder(abc.length());
        for (int k = 0; k < abc.length(); k++) {
            char c = abc.charAt(k);
            if (c < 256 && dic[c] > 0) {
                rs.append(" ");
            } else {
                rs.append(c);
            }
        }

        return rs.toString();
    }
 

 

 

 

测试报告

下面我们来看看这段代码:

相同功能的两段代码, 运行一下测试, 测试方法如下:

 

 

/**
 * User: ahuaxuan
 * Date: 2010-5-28
 * Time: 13:17:11
 */
    public static void main(String [] args) {
        for (int n = 0; n < 10; n++) {
            System.out.println("------------------------" + n);
            StringBuilder txt = new StringBuilder(1000);
            for (int k = 0; k < 100; k++) {
                txt.append(UUID.randomUUID().toString());
            }

            CharFilter pt = new CharFilter();
            String abc = txt.toString();
            long begin = System.currentTimeMillis();
            for (int k = 0; k < 10000; k++) {
                pt.escape(abc);
            }
            System.out.println("escape : " + (System.currentTimeMillis() - begin) + "ms");

            begin = System.currentTimeMillis();
            for (int k = 0; k < 10000; k++) {
                pt.newEscape(abc);
            }
            System.out.println("new escape : " + (System.currentTimeMillis() - begin) + "ms");
        }

    }
 

不到1k的一个文本, 每种方法调用100次, 最终得到的结果是:

 

 

ahuaxuan 写道
------------------------0
escape : 103ms
new escape : 67ms
------------------------1
escape : 60ms
new escape : 42ms
------------------------2
escape : 61ms
new escape : 48ms
------------------------3
escape : 58ms
new escape : 39ms
------------------------4
escape : 56ms
new escape : 39ms
------------------------5
escape : 80ms
new escape : 39ms
------------------------6
escape : 55ms
new escape : 40ms
------------------------7
escape : 55ms
new escape : 38ms
------------------------8
escape : 55ms
new escape : 38ms
------------------------9
escape : 59ms
new escape : 41ms
 

 

如果我们把对每个不到1K的文本的过滤调用上升到10000次, 那么测试结果是:

 

 

ahuaxuan 写道
------------------------0
escape : 627ms
new escape : 433ms
------------------------1
escape : 564ms
new escape : 390ms
------------------------2
escape : 624ms
new escape : 390ms
------------------------3
escape : 561ms
new escape : 385ms
------------------------4
escape : 564ms
new escape : 388ms
------------------------5
escape : 600ms
new escape : 391ms
------------------------6
escape : 559ms
new escape : 382ms
------------------------7
escape : 564ms
new escape : 394ms
------------------------8
escape : 573ms
new escape : 395ms
------------------------9
escape : 566ms
new escape : 406ms
 

 

文体大小和过滤次数上升之后, 优化之后的方法比原先的方法快了近200ms.

 

总结:

性能就像女人的胸, 挤一挤还是有的.

当然如果你觉得文中的手段是太入门级了, 那你可以看看ahuaxuan的这篇文章:

 

使用DFA实现文字过滤

 

 

8
1
分享到:
评论
4 楼 xiaopohai85707 2015-04-15  
优化算法与原来需求不符
3 楼 狂放不羁 2011-06-03  
之前也做过类似的需求,我的思路和你的类似,就是弄一个boolean类型的数组,true表示匹配,false表示不匹配.boolean[] filterChars;
2 楼 dongritengfei 2011-05-28  
追求细节!java为了开发效率当然会先不考虑一些细节的代码性能问题,如果有性能问题的时候再来追踪哪里是性能瓶颈,这样开发效率高一些。
1 楼 aroundworld2008 2010-08-26  
记得在有一个C面试题中,就是这样的,想一想这种问题,对于熟悉C语言的同学来说, 太小儿科了,所以C语言功底稍微好点的,这种问题压根不会去if else之类来过虑了!!

相关推荐

    Informatica性能调优(中级)

    本文档主要针对中级水平的性能调优提供一系列实用建议和技术细节。 #### 一、过滤表达式的优化 **1. 表达式与过滤器**: 尝试在Expression变换中评估表达式。将复杂的过滤逻辑放入Expression变换中,计算出一个布尔...

    Infomatica 性能调优2

    #### 一、性能调优概述 在《Infomatica性能调优2》中,主要介绍了如何优化Infomatica工具的性能,使其更高效地处理数据集成任务。该文档强调了针对不同版本的Infomatica(如PowerMart/PowerCenter 4.5X/4.6X/1.5X/...

    SQL性能调优方法特提供下载

    根据提供的文件信息,我们可以深入探讨SQL性能调优的相关知识点,特别是关于如何优化SQL查询语句以提高数据库查询效率。...总的来说,SQL性能调优是一个涉及多个层面的技术领域,需要不断实践和探索才能掌握其精髓。

    oracle 数据库性能调优

    ### Oracle数据库性能调优:深度解析与实践指南 在企业级应用中,Oracle...总之,Oracle数据库性能调优是一个既科学又艺术的过程,需要结合理论知识与实践经验,不断探索和优化,以实现最佳的数据库性能和应用效率。

    oracle 数据库性能调优技术 1 中文

    **数据库性能调优**是一项复杂而又重要的任务,它旨在通过一系列的技术手段提升系统的响应速度和整体性能。调优涉及到多个层面的知识,包括数据库设计、索引管理、查询优化等。 数据库性能调优不仅关系到用户满意度...

    Oracle数据库Sql性能调优

    **总结**:Oracle数据库的SQL性能调优是一个复杂但至关重要的任务。通过对SQL语句的结构、优化器的选择、索引的使用等方面进行细致的调整和优化,可以显著提高数据库系统的整体性能。以上提到的技巧只是冰山一角,...

    Redis 宝典 _ 基础、高级特性与性能调优

    在《Redis 宝典:基础、高级特性与性能调优》中,你可以深入学习以下几个方面的知识: 1. **Redis 基础**:了解 Redis 的安装、配置和启动过程,掌握客户端连接与命令交互方式。基础命令包括设置、获取和删除键值对...

    BEA WebLogic平台下J2EE调优攻略

    在BEA WebLogic平台上进行J2EE调优是确保企业级应用高效运行的关键步骤。以下是一些关键的调优策略: 1. **通用代码调优**: ...同时,性能调优不应只在出现问题后进行,而应贯穿于整个软件开发周期。

    数据库调优文档

    ### 数据库调优知识点 #### 一、SQL调整目标 SQL调整的核心目标在于提升查询效率,减少不必要的资源消耗。具体包括但不限于以下几点: 1. **去掉不必要的大表全表扫描**:全表扫描通常会导致大量的I/O操作,尤其是...

    Apache Pig的性能优化.pdf

    根据给定的文件信息,我们可以深入探讨Apache Pig的性能优化及其在大数据处理中的角色与优势。首先,让我们从Apache Pig的基本概念入手。 ### Apache Pig概述 Apache Pig是一种高生产力的数据流语言和执行框架,...

    任意字符排列组合工具 淘宝直通车关键字组合工具

    在IT行业中,排列组合是一种重要的数学概念,广泛应用于算法设计、数据分析和优化问题。淘宝直通车关键字组合工具就是基于这...在实际应用中,工具的设计和优化涉及到算法选择、性能调优以及业务逻辑等多个层面的知识。

    informix sql性能分析

    - [IBM DeveloperWorks: Informix SQL性能调优技巧](http://www.ibm.com/developerworks/cn/db2/library/techarticles/dm-0409fan/index.html) - [IBM DeveloperWorks: Informix 数据库性能优化技术]...

    Tomcat调优配置技巧[参考].pdf

    Tomcat调优是提高应用程序性能的关键步骤,尤其对于处理高并发和大数据量的应用来说更为重要。以下是一些关键的Tomcat调优配置技巧: 一、启用Gzip压缩 为了减少网络流量,可以在Tomcat配置中启用Gzip压缩。在`...

    DB2 9 中 15 个 pureXML 性能最佳实践

    虽然传统的DB2性能调优原则如CPU/内存/磁盘配置平衡、表空间和缓冲池调优、锁定和日志记录等同样适用于XML数据,但针对XML数据还有一系列特定的性能考虑。 以下是15个pureXML性能最佳实践: 1. **明智选择XML文档...

    J2EE程序的性能优化技巧

    3. 使用过滤器:过滤器可以预先处理请求和响应,提高效率,比如GZIP压缩、字符集转换等。 五、EJB问题 Enterprise JavaBeans(EJB)是J2EE的重要组成部分,优化EJB性能需要注意: 1. 减少EJB远程调用:远程调用比...

    oracle性能优化(内部高级培训文档)

    Oracle性能优化是一个复杂而深入的主题,它涉及到数据库的多个层面,包括查询优化、索引策略、内存管理等。以下是对标题和描述中提及的一些关键知识点的详细解释: 1. **选用适合的ORACLE优化器** Oracle的优化器...

    基于Python的协同过滤算法的设计与实现.zip

    协同过滤(Collaborative Filtering,简称CF)是一种广泛应用于推荐系统中的算法,它基于用户的行为数据,通过发现用户的兴趣相似性来预测用户对未评价物品的评分或偏好。本项目将详细探讨如何在Python环境中设计并...

    Mysql性能优化 MYSQL

    对于依赖MySQL的企业或项目来说,进行合理的性能调优不仅能够显著提升系统处理能力,还能有效降低硬件成本。 #### 二、MySQL性能优化的主要方面 ##### 2.1 Schema设计 **2.1.1 数据库表结构设计原则** 1. **消除...

Global site tag (gtag.js) - Google Analytics