`
kernaling.wong
  • 浏览: 78809 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类

Java判断中文字符的性能最优方案

 
阅读更多

    开端与场景

    接着上一篇文章的地区分词匹配,最近发现有一些内容中全部为英文或者直接就是一些连接URL,理论上根本不可能产生地区特征的关键字,之前的做法却把这些也进行了分词和匹配了。所以一个比较高效的方式就是把文章内容中非中文的字符过滤掉。

    集群的数据存储了约8亿的文章,现在进行一次索引的 rebuild .

    这涉及了一个对中文字符的判断及过滤了,想必大家对此也很多想法。网上也介绍了几种方式。这里不讨论是否能实现的问题,是讨论实现速度最快的的问题。

 

    方法一:

        也是网上最多人使用的方式通过正则表达式,方便又快捷

        string.matches( "[\u4e00-\u9fa5]" );

 

   方法二:

       也有部分人使用

       具体,通过JDK内置的 uncode 变量去判断

private static final boolean isChinese(char c) {
    Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
    if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
      || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
      || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
      || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
      || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
      || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
     return true;
    }
    return false;
   }

 

    方法三:

     通过找到中文 unicode 的范围,把中文的判断变成简单的 int 判断从而达到最高的性能与效率

  

        // 中文的 char 范围
	// by kernaling.wong
	private static int cn_min = (int)"一".charAt(0); //\u4e00
	private static int cn_max = (int)"龥".charAt(0); //\u9fa5
        // 方法 3
	// 通过最原始的 unicode 范围判断
	// 把中文变成 int 的判断
	private static final boolean isChinese3(char c) {
	   
		int char_int = (int)c;
		if( char_int < cn_min || char_int > cn_max  ){
			return false;
		}else{
			return true;
		}
		
	}

 

     对比的测试效果

     我做了一个三种方式性能对比,在判断 100W 个字符的时间,如下图所示

   

   

  

    以下是测试的类文件,复制后,直接可以执行

   

package com.test.logs;

/**
 * 
 * @author kernaling.wong
 * 
 * 		测试中文判断方式的效率与性能
 *
 */
public class Test {

	// 中文的 char 范围
	// by kernaling.wong
	private static int cn_min = (int)"一".charAt(0); //\u4e00
	private static int cn_max = (int)"龥".charAt(0); //\u9fa5
		
	public static void main(String[] args) {
		
		try{
			
			String s = "你";
			long start = System.currentTimeMillis();
			for(int i=0;i<100*10000;i++){				
				isChinese(s);
			}
			start = System.currentTimeMillis() - start;
			System.out.println("function 1 : " + start);
			
			start = System.currentTimeMillis();
			for(int i=0;i<100*10000;i++){				
				isChinese2(s.charAt(0));
			}
			start = System.currentTimeMillis() - start;
			System.out.println("function 2 : " + start);
			
			
			start = System.currentTimeMillis();
			for(int i=0;i<100*10000;i++){				
				isChinese3(s.charAt(0));
			}
			start = System.currentTimeMillis() - start;
			System.out.println("function 3 : " + start);
			
			
		}catch(Exception ex){
			
			ex.printStackTrace();
			
		}
	}
	
	// 方法 1
	// 通过正则表达式
	private static final boolean isChinese(String c) {
	   return c.matches("[\u4e00-\u9fa5]");
	}
	
	// 方法 2
	// 通过JDK内置的 unicode 变量判断
	private static final boolean isChinese2(char c) {
	    Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
	    if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
	      || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
	      || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
	      || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
	      || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
	      || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
	     return true;
	    }
	    return false;
	}
	
	// 方法 3
	// 通过最原始的 unicode 范围判断
	// 把中文变成 int 的判断
	private static final boolean isChinese3(char c) {
	   
		int char_int = (int)c;
		if( char_int < cn_min || char_int > cn_max  ){
			return false;
		}else{
			return true;
		}
		
	}
	
	
}

 

    总结

       本来对于 这一个中文的判断方式,其实只是在原来的基础上添加一个方法而已,但也正因为这样子导致了性能上有所偏差,在未实现之前,跑 1W 的数据到 solr 用了 19秒,但实现后,同样数据到 solr 用了 9 秒。节省了足足10秒的时间。可能很多人不理解这样子一个简单实现的功能为何劳师动众,在普通的注重功能上实现来说,其实用方法一,方法二,方法三都看不出差别,但对于大数据的集群来说,丝毫的性能差别经过累积却放大很多倍。所以才需要对性能和效率的执着追求。

                                                                                       欢迎连载,请注明来源及作者

                                                                                        http://kernaling-wong.iteye.com/blog/2079091

                                                                                         by kernaling.wong @ 2014.06.13

  • 大小: 103.5 KB
分享到:
评论

相关推荐

    分词程序java源码

    10. **性能优化**:为了实现高效的分词速度,开发者可能会使用缓存技术、字符串池以及Java的并发库进行性能优化。 " spliter "作为压缩包内的文件名,很可能是指分词器的主类或者核心模块,负责将输入的文本进行...

    java_algorithm_Daquann.rar_java算法

    位运算在某些特定场景下可以提供高效的解决方案,如求最大公约数、判断奇偶性、快速幂运算等。 这个"java_algorithm_Daquann.rar"的源码包很可能会包含以上提到的各种算法的Java实现,通过阅读和理解这些代码,...

    各种算法的java实现

    10. **字符串处理**:Java中的String类提供了丰富的操作方法,如模式匹配、替换、分割等,涉及到KMP算法、Boyer-Moore算法等字符串匹配策略。 在《各种算法java实现.docx》这个文档中,你可能会找到以上算法的详细...

    java 解惑.pdf

    - **解惑**:字符串拼接时需要注意内存效率和性能问题。使用`StringBuilder`或`StringBuffer`类进行拼接可以提高效率,特别是在处理大量字符串的情况下。 **谜题14:转义字符的溃败** - **描述**:涉及到转义字符的...

    LeetCode-Solutions:Leetcode Java最佳解决方案

    - 字符串:涉及到字符串处理,如回文判断、最长公共前后缀等。 - 树结构:二叉树的遍历、平衡二叉树、最近公共祖先等。 - 链表:链表操作,如两链表相交、删除中间节点等。 - 哈希表:用于快速查找和去重,如两...

    JAVA三大框架优缺点

    3. **高性能:** Hibernate使用Java反射机制而非字节码增强技术实现了透明性,这有助于提高应用程序的性能。 4. **易于维护:** 当数据库结构发生变化时,通过调整Hibernate的映射配置文件即可,减少了对业务代码的...

    数据结构与算法(JAVA语言版解密)

    - Java中的字符串是不可变的对象,使用`String`类来表示。字符串可以通过拼接、索引访问等方式进行操作。 - **数组** - 数组是一种基本的数据结构,用于存储固定大小的同类型元素。数组可以通过索引来访问或修改...

    程序设计协会第一届九韶杯题解 .pdf

    该题目要求通过栈操作对字符进行处理,并根据栈的长度来判断字符串中的特定模式。可能涉及到字符串解析、数据结构的操作和模式识别。 C题“斐波那契”可能要求解决和斐波那契数列相关的问题,这是一个典型的递归...

    华为面试上机题(二)

    12. 代码可读性与健壮性:在编写代码时,应该注意代码的可读性,例如合理地使用变量名和注释来解释代码逻辑,以及在方案一中使用for循环的嵌套和条件判断来确保代码的正确执行。 13. 时间复杂度与空间复杂度:动态...

    LeetCode:解决LeetCode问题的Java解决方案

    在LeetCode平台上,Java是一种广泛使用的编程语言来解决算法和数据结构的问题。这些问题涵盖了从基础到高级...在实践中,还需要注意代码的优化、错误处理和性能调优,这些都是成为一名优秀的Java程序员必不可少的部分。

    数据结构与算法-java版

    - **Huffman树及Huffman编码**:通过构建Huffman树得到最优的二进制编码方案。 #### 七、图 - **图的定义** - **图及基本术语**:图是由顶点集和边集组成的集合,分为有向图和无向图。 - **抽象数据类型**:...

    Java数据结构和算法

    Java数据结构和算法是计算机科学...总之,Java数据结构和算法是开发高效程序的基础,深入学习和理解这些概念,能够帮助我们设计出更好的解决方案,提高代码质量。无论是面试还是实际项目开发,这都是不可或缺的知识点。

    华中科技大学计算机学院第四届程序设计大赛初赛试题[1].pdf

    - **性能优化**:鼓励参赛者编写高效代码,关注算法的时间复杂度和空间复杂度,追求优雅的解决方案。 - **资源管理**:避免在函数内部定义大数组,以减少栈空间的消耗,提倡合理利用全局变量。 ### 2. 字符串处理与...

    前几年的蓝桥杯的一些试题

    8. **编程语言基础**:如C/C++/Java/Python等,熟悉其语法特性和性能特性,了解如何写出高效且优雅的代码。 9. **逻辑思维**:解决复杂问题时,良好的逻辑思维能力能帮助分析问题,找到最优解决方案。 10. **调试...

    Algorithms-Exercises:Java算法练习(第4版)

    《Algorithms-Exercises-master》这个压缩包很可能是包含上述知识点的Java代码实现,每个子文件对应一个具体的算法练习,学习者可以通过阅读和运行这些代码来加深对算法的理解,并且可以尝试自己编写解决方案,以...

    数据结构与算法思维导图1

    在编程中,正确地组织和操作数据可以显著提升程序的性能。以下是一些主要的数据结构和算法的详细说明: 1. **一维数据结构**: - **数组**:是最基本的数据结构,它提供了直接访问元素的能力,通过索引进行操作。...

    Leetcode-2月:发布解决方案以应对2月的编码挑战

    本资源包“Leetcode-February-master”包含了针对这些挑战的解决方案,以下是基于Java语言的解题知识点的详细分析: 1. **基础语法**:在解决LeetCode问题时,Java的基础语法是必不可少的,包括变量声明、条件语句...

Global site tag (gtag.js) - Google Analytics