关于java:你只会用-split试试-StringTokenizer性能可以快-4-倍

42次阅读

共计 3735 个字符,预计需要花费 10 分钟才能阅读完成。

咱们都晓得,宰割字符串要应用 String 的 split() 办法,split 办法尽管深入人心,应用也简略,但效率太低!

其实在 JDK 中,还有一个性能很强的纯字符串宰割工具类:StringTokenizer

这个类在 JDK 1.0 中就推出来了,但在理论工作却发现很少有人应用,网上有人说不倡议应用了,甚至还有人说曾经废除了,真的是这样吗?

StringTokenizer 被废除了吗?

栈长翻阅了一些材料,原来在 Oracle JDK 官网文档中曾经有了形容,这是最新的 Oracle JDK 15 的官网文档对于 StringTokenizer 的阐明:

StringTokenizer is a legacy class that is retained for compatibility reasons although its use is discouraged in new code. It is recommended that anyone seeking this functionality use the split method of String or the java.util.regex package instead.

参考:https://docs.oracle.com/en/ja…

StringTokenizer 原来是一个遗留类, 并未被废除 ,只是出于兼容性起因而被保留,在新代码中曾经不激励应用它了,倡议应用 String 的 split 办法或 java.util.regex 包代替。

再来看 StringTokenizer 类的源码:

能够看到 StringTokenizer 类并未标识 @Deprecated,阐明在后续的版本中也还能够持续应用,官网还会持续保留,并不会进行删除。

就像 JDK 汇合中的 Vector 和 Hashtable 类一样,尽管它们略显轻便,但并不阐明它们没有用了,另外,它们也不存在致命缺点,所以始终保留到当初并未破除掉。

StringTokenizer 没人用了吗?

答案:非也!

栈长在最新的 Spring 5.x 框架 StringUtils 工具类中就发现了 StringTokenizer 的应用身影:

org.springframework.util.StringUtils#tokenizeToStringArray

另外,栈长还看到了一篇《Faster Input for Java》的文章,其中就介绍了他们是应用 StringTokenizer 来宰割字符串的, 其效率是 string.split() 的 4 倍

We split the input line into string tokens, since one line may contain multiple values. To split the input, StringTokenizer is 4X faster than string.split().

参考:https://www.cpe.ku.ac.th/~jim…

所以,即便 JDK 不激励应用它了,但它并未被破除,并且性能还这么强,在一些对性能比拟敏感的零碎中,或者对性能比拟有要求的编程比赛中,StringTokenizer 就能施展重要作用。

所以,大胆用吧,StringTokenizer 还是能够用的,用的好还能出奇效!另外,往期 Java 技术系列文章我也曾经整顿好了,关注公众号 Java 技术栈,在后盾回复:java,能够获取浏览,十分齐全。

StringTokenizer vs split

说了这么多,置信大部分人都只用过 split,而没用过 StringTokenizer,那么栈长明天就来比照下这两个字符串宰割法的性能及利弊。

测试代码如下:

import java.util.Random;
import java.util.StringTokenizer;

/**
 * @author: 栈长
 * @from: 公众号 Java 技术栈
 */
public class SplitTest {

    private static final int MAX_LOOP = 10000;

    /**
     * @author: 栈长
     * @from: 公众号 Java 技术栈
     */
    public static void main(String[] args) {StringBuilder sb = new StringBuilder();
        System.out.println(sb.toString());
        for (int i = 0; i < 1000; i++) {sb.append(new Random().nextInt()).append(" ");
        }
        split(sb.toString());
        stringTokenizer(sb.toString());
    }

    /**
     * @author: 栈长
     * @from: 公众号 Java 技术栈
     */
    private static void split(String str) {long start = System.currentTimeMillis();
        for (int i = 0; i < MAX_LOOP; i++) {String[] arr = str.split(" ");
            StringBuilder sb = new StringBuilder();
            for (int j = 0; j < arr.length; j++) {sb.append(arr[j]);
            }
        }
        System.out.printf("split 耗时 %s ms\n", System.currentTimeMillis() - start);
    }

    /**
     * @author: 栈长
     * @from: 公众号 Java 技术栈
     */
    private static void stringTokenizer(String str) {long start = System.currentTimeMillis();
        for (int i = 0; i < MAX_LOOP; i++) {StringTokenizer stringTokenizer = new StringTokenizer(str, " ");
            StringBuilder sb = new StringBuilder();
            while (stringTokenizer.hasMoreTokens()) {sb.append(stringTokenizer.nextToken());
            }
        }
        System.out.printf("StringTokenizer 耗时 %s ms", System.currentTimeMillis() - start);
    }

}

在我本机测试后果如下:

测试次数 split StringTokenizer
1 1ms 1ms
10 7ms 3ms
100 30ms 16ms
1000 129ms 51ms
10000 570ms 486ms
100000 3816ms 3130ms

从测试数据看,尽管 StringTokenizer 有一点性能劣势,但并不太显著,我并没有测试出有 4 倍的性能差距,可能和测试数据、测试方法、以及测试的 JDK 版本有关系。

而后,我再把 split 测试方法中的 "" 改成 "\\s"

测试次数 split StringTokenizer
1 6ms 1ms
10 25ms 4ms
100 90ms 20ms
1000 240ms 59ms
10000 835ms 481ms
100000 5616ms 3362ms

把 split 办法改成正则表达式再测试,这下差距就显著了。

咱们都晓得解析正则表达式会比较慢一点,这很失常,但 StringTokenizer 并不反对传入正则表达式,只能应用字符串作为分隔符,所以这测试后果就没多大意义了,这就是症结了。。

总结

尽管 JDK 不激励应用 StringTokenizer 了,但并不阐明它不能用了,相同,如果你的系统对性能有十分严格的要求,又不是很简单的字符串宰割,好好应用它反而能够带来高效。

但话又说回来,个别的应用程序用 split 也就够了,因为它够简略、又反对正则表达式,在个别的利用中也不会存在像文中测试的大批量的字符串循环宰割,另外,StringTokenizer 在单次宰割的性能上也没有性能劣势。

最初,对于字符串的宰割办法,咱们除了字符串自身的 split 办法,咱们还要晓得 StringTokenizer 这个类,多晓得点不是好事。另外,在 Spring、Apache Commons 工具类中也都有封装好的 StringTokenizer 工具类,有趣味的能够间接拿去用。

好了,明天的分享就到这里了,前面栈长我会更新更多好玩的 Java 技术文章,关注公众号 Java 技术栈第一工夫推送,不要走开哦。

本节教程所有实战源码已上传到这个仓库:

https://github.com/javastacks…

最初,感觉我的文章对你用播种的话,动动小手,给个在看、转发,原创不易,栈长须要你的激励。

版权申明:本文系公众号 “Java 技术栈 ” 原创,原创实属不易,转载、援用本文内容请注明出处,禁止剽窃、洗稿,请自重,尊重大家的劳动成果和知识产权,剽窃必究。

近期热文举荐:

1.1,000+ 道 Java 面试题及答案整顿 (2021 最新版)

2. 终于靠开源我的项目弄到 IntelliJ IDEA 激活码了,真香!

3. 阿里 Mock 工具正式开源,干掉市面上所有 Mock 工具!

4.Spring Cloud 2020.0.0 正式公布,全新颠覆性版本!

5.《Java 开发手册(嵩山版)》最新公布,速速下载!

感觉不错,别忘了顺手点赞 + 转发哦!

正文完
 0