03 June 2016

这篇文章说下,lang包中基本类型相关的工具类,说基本类型其实有点不太准确,主要是针对字符串(Strings),数字(Nums), 日期(Times)的工具类。 下面一个一个类来看了,其实鄙人java基础很不扎实,这次趁着阅读基础的工具类的机会也好好复习巩固下基础。有说的不对的地方,欢迎批评指正。辣么,开始吧。

Strings

字符判断

  • 判断是否是中文字符,先来段热气腾腾的代码:

    /**
     * 是中文字符吗?
     * 
     * @param c
     *            待判定字符
     * @return 判断结果
     */
    public static boolean isChineseCharacter(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.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B
            || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
            || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
            || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION) {
            return true;
        }
        return false;
    }

好吧,还可以这样判断是否是中文字符。我也是涨姿势了,遥想当年,哦不,也许是上上个月,俺用着蹩脚的正则表达式来判断一个字符是否是中文,太苦逼了。给我们这些总是不能熟练使用正则的同胞一个福音。 查了下API,Character.UnicodeBlock类的of方法,返回的一个指定字符的Unicode块对象。 比如CJK_UNIFIED_IDEOGRAPHS就表示中,日,韩等一类国家的这种表意文字(和字母一类的区分)那这个肯定包含汉字字符了。

  • 接下来看对全半角的判断

    /**
     * 判断字符是否为全角字符
     * 
     * @param c
     *            字符
     * @return 判断结果
     */
    public static boolean isFullWidthCharacter(char c) {
        // 全角空格为12288,半角空格为32
        // 其他字符半角(33-126)与全角(65281-65374)的对应关系是:均相差65248
        // 全角空格 || 其他全角字符
        if (c == 12288 || (c > 65280 && c < 65375)) {
            return true;
        }
        // 中文全部是全角
        if (isChineseCharacter(c)) {
            return true;
        }
        // 日文判断
        // 全角平假名 u3040 - u309F
        // 全角片假名 u30A0 - u30FF
        if (c >= '\u3040' && c <= '\u30FF') {
            return true;
        }
        return false;
    }

这个方法同样使用字符编码来对全角字符进行判断归类,方法中将全角字符归为四类:

  • 全角空格:unicode码值为:12288
  • 其他全角字符,入逗号”,”,句号”。”等,码值为从65281至65374。
  • 中文字符,通过调用isChineseCharacter也可以看出,对于日韩文字也划分到全角字符中去。
  • 日文假名

上面代码中作者也注释了,除了空格,其他字符的全角和半角形式相差65248,所以就有了下面的全半角转换方法:


    public static char toHalfWidthCharacter(char c) {
        if (c == 12288) {//空格转换
            return (char) 32;
        } else if (c > 65280 && c < 65375) { //其他字符转换
            return (char) (c - 65248);
        }
        return c;
    }

接下来的几个全角和半角的相关操作和转换,以及计算字符串长度基本都是调用上面这三个方法来进行;就不细说了。

字符转换

  • 复制字符串,将一个字符串复制N个放在一个字符串中,核心代码如下所示。说实话,平时在使用StringBuilder和StringBuffer的时候很受初始化字符串长度。 其实如果在能确认字符串长度的时候,加入长度构造参数,对于提升性能是个好习惯。

        StringBuilder sb = new StringBuilder(cs.length() * num);
        for (int i = 0; i < num; i++)
            sb.append(cs);
        return sb.toString();
  • 字符串首字母大小写。好吧,曾经有类似下面这么写代码的撅起屁股排一排,让兽兽打一下
        String s = "hello world";
       return s.substring(0, 1).toUpperCase()+s.substring(1);
        System.out.println(result);

下面来看看兽兽们给我们演示的姿势;哦不,是代码:


    String s = "hello world";
    char c = s.charAt(0);
    return new StringBuilder(len).append(Character.toUpperCase(c))
                                         .append(s.subSequence(1, len))
                                         .toString();

效率上熟优熟劣,显而易见。

这里可以更进一步,既然,刚才说到全半角字符编码相差是固定的,那么大写字母和小写字母的码值是不是一定的,如果是一定的,那么就可以使用编码值便宜来处理咯:


    String s = "hello world";
    char[] c=s.toCharArray();
    c[0]-=32;//大写字母的码值都比小写字母小32
    return String.valueOf(cs);

关于charAt的用法,这两个方法也用到了:startsWithChar,endsWithChar,对于类似这种针对确定位置的字符进行操作的需求,可以多用charAt。忘了subString吧

后面还有一些字符串切割,进制转换的封装;以及个人感觉较个性化的需求封装了(反正我是比较少用嗒),比如:removeFirst,移除匹配的首字符,isin:某组字符串中是否包含一个字符串 lowerWord:将一个字符串由驼峰式命名变成分割符分隔单词(好吧,这个方法可用于将java bean转换为表名称)

类似一些与业务相关的需求,可以自行去封装了。

不过看下来这个Strings的封装类,总体来说,学到了两点。针对字符定位多使用charAt,针对字符类型的判断,多使用字符编码值来判断。在提高效率上很有益处。 当然一般项目中的性能优化,以上这些对系统性能影响较小;更多的优化集中在网络连接,数据库连接池,IO方面居多。 不过对于cs应用以及一些底层框架,还是要在每一行代码上的性能进行尽量优化。

本来想把Nums和Times也在这里一并写下来的,但是自己不惜还长文,所以留做后面再来一篇说它们吧。

Nums

Times





Fork me on GitHub