文章摘自:http://sunflowers.iteye.com/blog/698863
作者用底层代码和亲身试验告诉我们,equals的效率相比另外两个慢很多,在大数量级的运算中这个常数时间也是值得斟酌的。
//比较 方法一,大多数人都这么比较 String param = config.getInitParameter("log-level"); if (param != null && !"".equals(param)) { final Level level = Log.getLevel(param); if (level != null) Log.lookup("org.zkoss").setLevel(level); else log.error("Unknown log-level: "+param); } //比较 方法二,(而我研究的源码基本都这么比较) String param = config.getInitParameter("log-level"); if (param != null && param.length() > 0) { final Level level = Log.getLevel(param); if (level != null) Log.lookup("org.zkoss").setLevel(level); else log.error("Unknown log-level: "+param); } // 下面我们看一下equals,length,isEmpty的源码 //String中equals方法内部代码 public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = count; if (n == anotherString.count) { char v1[] = value; char v2[] = anotherString.value; int i = offset; int j = anotherString.offset; while (n-- != 0) { if (v1[i++] != v2[j++]) return false; } return true; } } return false; } //String.length()的源码 /** * Returns the length of this string. * The length is equal to the number of <a href="Character.html#unicode">Unicode * code units</a> in the string. * * @return the length of the sequence of characters represented by this * object. */ public int length() { return count; } //String.isEmpty的源码 /** * Returns <tt>true</tt> if, and only if, {@link #length()} is <tt>0</tt>. * * @return <tt>true</tt> if {@link #length()} is <tt>0</tt>, otherwise * <tt>false</tt> * * @since 1.6 */ public boolean isEmpty() { return count == 0; }
仅从代码多少以及逻辑判断来看,length,isEmpty都非常简单,对于一般比较判断来说,
首先我猜测:length,isEmpty是相差无几的,equals方法就望尘莫及了,
下面做一个测试,证明我们的猜测
测试代码如下
private static final String sunflower = "sunflower"; private static final int COUNT= 1000000000; public static void main(String[] args) { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("开始计算...\n"); Long begin = System.currentTimeMillis(); for (int j = 0; j < COUNT; j++) { testEmptyByLength(sunflower); } calculateDuration("length test", begin); begin = System.currentTimeMillis(); for (int j = 0; j < COUNT; j++) { testEmptyByEmpty(sunflower); } calculateDuration("empty test", begin); begin = System.currentTimeMillis(); for (int j = 0; j < COUNT; j++) { testEmptyByEquals(sunflower); } calculateDuration("equals test", begin); } public static void calculateDuration(String method, long begin) { System.out.println(method + "\t:" + (System.currentTimeMillis() - begin) / 1000); } public static boolean testEmptyByLength(String str) { return str == null || str.length() < 1; } /** * empty方法是jdk1.6添加的方法,如果是早期版本不兼容 * * @param str * @return */ public static boolean testEmptyByEmpty(String str) { return str == null || str.isEmpty(); } public static boolean testEmptyByEquals(String str) { return "".equals(str); }
输出结果:
开始计算(s)
length test :0
empty test :0
equlas test :8
结论:
String.isEmpty()方法是jdk1.6中添加的,其方法体和length()方法一样,从性能和兼容性,length()更好,
所以如果对字符串非严格判断是否为空,建议使用String.length>0判断,如果严格判断是否全部为" "字符,就要自己写或者用common lang StringUtils.isBlank了
isBlank方法代码补充:
/** * <p>Checks if a String is whitespace, empty ("") or null.</p> * * <pre> * StringUtils.isBlank(null) = true * StringUtils.isBlank("") = true * StringUtils.isBlank(" ") = true * StringUtils.isBlank("bob") = false * StringUtils.isBlank(" bob ") = false * </pre> * * @param str the String to check, may be null * @return <code>true</code> if the String is null, empty or whitespace * @since 2.0 */ public static boolean isBlank(String str) { int strLen; if (str == null || (strLen = str.length()) == 0) { return true; } for (int i = 0; i < strLen; i++) { if ((Character.isWhitespace(str.charAt(i)) == false)) { return false; } } return true; }