Java中String.split的坑
来源:互联网 发布:网络电视盒子排行榜 编辑:程序博客网 时间:2024/06/05 08:40
在看阿里的Java规范的时候看到了这一个东西,
于是乎找了一些这个相关的一些情况,因为以前没碰到过,看到了一篇不错的文章,所以转载过来了。文章地址:http://yinny.iteye.com/blog/1750210
System.out.println(":ab:cd:ef::".split(":").length);//末尾分隔符全部忽略 System.out.println(":ab:cd:ef::".split(":",-1).length);//不忽略任何一个分隔符 System.out.println(StringUtils.split(":ab:cd:ef::",":").length);//最前面的和末尾的分隔符全部都忽略,apache commons System.out.println(StringUtils.splitPreserveAllTokens(":ab:cd:ef::",":").length);//不忽略任何一个分隔符 apache commons 输出: 4 6 3 6看了下jdk里String类的public String[] split(String regex,int limit)方法,感觉平时不太会用这方法,以为在用正则表达式来拆分时候,如果匹配到的字符是最后一个字符时,会拆分出两个空字符串,例如"o"split("o",5) or "o"split("o",-2)时候 结果是"" "" 也就是下图中红框里的内容,所以平时一般都用split(String regex) 方法,其实也就等同于split(String regex,0)方法,把结尾的空字符串丢弃!
String的split方法用到的参数是一个正则式,虽然强大,但是有时候容易出错。而且string并没有提供简化版本。org.apache.commons.lang.StringUtils提供的split改变了这一状况,开始使用完整的字符串作为参数,而不是regex。同时,对类似功能的jdk版本的StringTokenizer,在内部方法splitWorker中有段注释:Direct code is quicker than StringTokenizer.也就是说,这个是更快的一个工具了~~
StringUtils里的split和splitPreserveAllTokens 底层都是调用splitWorker方法实现的
下面分别来理解下两个私有的splitWorker方法:
private static String[] splitWorker(String str, char separatorChar, boolean preserveAllTokens) { // Performance tuned for 2.0 (JDK1.4) if (str == null) { return null; } int len = str.length(); if (len == 0) { return ArrayUtils.EMPTY_STRING_ARRAY; } List list = new ArrayList(); int i = 0, start = 0; boolean match = false; boolean lastMatch = false; while (i < len) { if (str.charAt(i) == separatorChar) { if (match || preserveAllTokens) { list.add(str.substring(start, i)); match = false; lastMatch = true; } start = ++i; continue; } lastMatch = false; match = true; i++; } if (match || (preserveAllTokens && lastMatch)) { list.add(str.substring(start, i)); } return (String[]) list.toArray(new String[list.size()]); }是一个核心方法,用于拆分字符串,其中字符c表示分隔符,另外布尔变量b表示c在首尾的不同处理方式。为真,则在首位留一个""的字符串。但是在中间是没有作用的。该方法执行如下操作:
如果字符串为null,则返回null。
如果字符串为"",则返回""。
用i作为指针遍历字符串,match和lastMatch分别表示遇到和最后遇到可分割的内容。
如果字符串中第一个就遇到c,则看b的值,如果为真,则会在结果数组中存入一个""。如果没遇到,match置真,lastMatch置假,表示有要分割的内容。
一旦遇到c,则在结果数组中输出字符串在i之前的子字符串,并把起始点调整到i之后。且match置假,lastMatch置真。
遍历结束,如果match为真(到最后也没有遇到c),或者lastMatch和b同为真(最后一个字符是c),则输出最后的部分(如果是后者,则会输出一个"")。
private static String[] splitWorker(final String str, final String separatorChars, final int max, final boolean preserveAllTokens) { // Performance tuned for 2.0 (JDK1.4) // Direct code is quicker than StringTokenizer. // Also, StringTokenizer uses isSpace() not isWhitespace() if (str == null) { return null; } final int len = str.length(); if (len == 0) { return ArrayUtils.EMPTY_STRING_ARRAY; } final List<String> list = new ArrayList<String>(); int sizePlus1 = 1; int i = 0, start = 0; boolean match = false; boolean lastMatch = false; if (separatorChars == null) { // Null separator means use whitespace while (i < len) { if (Character.isWhitespace(str.charAt(i))) { if (match || preserveAllTokens) { lastMatch = true; if (sizePlus1++ == max) { i = len; lastMatch = false; } list.add(str.substring(start, i)); match = false; } start = ++i; continue; } lastMatch = false; match = true; i++; } } else if (separatorChars.length() == 1) { // Optimise 1 character case final char sep = separatorChars.charAt(0); while (i < len) { if (str.charAt(i) == sep) { if (match || preserveAllTokens) { lastMatch = true; if (sizePlus1++ == max) { i = len; lastMatch = false; } list.add(str.substring(start, i)); match = false; } start = ++i; continue; } lastMatch = false; match = true; i++; } } else { // standard case while (i < len) { if (separatorChars.indexOf(str.charAt(i)) >= 0) { if (match || preserveAllTokens) { lastMatch = true; if (sizePlus1++ == max) { i = len; lastMatch = false; } list.add(str.substring(start, i)); match = false; } start = ++i; continue; } lastMatch = false; match = true; i++; } } if (match || preserveAllTokens && lastMatch) { list.add(str.substring(start, i)); } return list.toArray(new String[list.size()]); }也是一个核心方法,用于拆分字符串,其与上一个方法的不同之处在于其分隔符用字符串表示一组字符,且增加一个max变量,表示输出的字符串数组的最大长度。另外注意该方法的b如果为真,会在首尾及中间起作用,且如果分隔符字符串长度大于1,则数组中的""会更多(根据分隔符字符的数量)。该方法执行如下操作:
如果字符串为null,则返回null。
如果字符串为"",则返回""。
之后的处理分三种情况,分别是分隔符字符串为null,则默认为" ";分割符字符串长度为1;分割符字符串为普通字符串。这三种处理的不同只是在当前遍历中的字符的判断问题。
1.利用Character.isWhitespace方法判断每个字符是否为" "。
2.先把字符串转化为一个char,然后就和前一个splitWorker方法类似。
3.利用indexOf方法查找当前字符是否在分隔符字符串中,然后就和前一个splitWorker方法类似。
需要注意的是,如果输出的数组的数量已经等于max的值,则把指针直接挪到最后,等待下次遍历的时候直接跳出。同时由于lastMatch和match都置为假,最后也不会输出""了。
遍历结束,如果match为真(到最后也没有遇到c),或者lastMatch和b同为真(最后一个字符在分隔符字符串中),则输出最后的部分(如果是后者,则会输出一个"")。
(以上内容为复制内容,如有错误,请到链接原文查看)
阅读全文
0 0
- Java中String.split的坑
- JAVA中String的split
- java中String 的split("\\.")
- java中String.split()
- java中String.split()的注意事项
- java中String的split()方法
- Java String中split的奇怪现象
- Java中String类的split方法
- java中string 的split函数
- Java 中String的split函数简介
- java中String.split()的常用方法
- Java 中String.split()的用法简介
- c++中string的仿java string的split接口
- java String中split()用法
- Java中String.split()用法
- String.split的坑
- java中String的split的详细用法
- Java中String的分词方法split的使用
- 如何使用XListview实现listview的下拉刷新和上拉加载
- 使用cordova插件后,unknown provider问题
- Euclidean algorithm
- 学习资源
- 完美解决echarts的柱状图和折线图的点击非图表图形元素不会触发事件
- Java中String.split的坑
- Go语言入门
- 使用js设置element的属性
- 顺序表的创建和就地逆置
- C++区别于其他语言的知识点总结
- Spring Boot + Spring Data + Elasticsearch实例
- leetcode题解-125. Valid Palindrome && 680. Valid Palindrome II
- 登陆界面
- Nginx获取客户真实的IP地址