这篇文章说下,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也在这里一并写下来的,但是自己不惜还长文,所以留做后面再来一篇说它们吧。