String.split()方法你可能不知道的一面
  一、问题
  java中String的split()是我们经常使用的方法,用来按照特定字符分割字符串,那么我们看以下一段代码:
  public void splitTest() {
  String str = "aaa|bbb|ccc";
  String[] array = str.split("|");
  System.out.println(Arrays.toString(array));
  }
  是不是感觉很简单,就是吧str按照"|"分割,结果就是[aaa,bbb,ccc]嘛。如果你这么想,那么以后在用这个方法时你可能会犯下大错,把程序跑起来,你会惊讶的发现程序输入如下结果:
  [, a, a, a, |, b, b, b, |, c, c, c]
  为什么会出现这种情况呢?我们再来运行一下str.split("");就会发现结果和之前的结果一样,也就是说我们使用"|"分割的时候其实split是按照空字符分割的。
  二、探究
  为了找到原因,我们在来使用其他几种字符测试一下,结果如下:
  0:[aaa, bbb, ccc]
  $:[aaa$bbb$ccc]
  ,:[aaa, bbb, ccc]
  *:异常java.util.regex.PatternSyntaxException: Dangling meta character '*' near index 0
  ^:[aaa^bbb^ccc]
  我们会发现对于数字,","结果是正确的,而对于特殊字符,结果都不正确,而且如果经验丰富,你可能已经发现,这些特殊字符都是正则表达式中的匹配符,而那个异常也很明确的说明了这一点。
  因此,我们可以猜测在split内部使用了正则表达式来匹配并分割字符串。那么现在又有一个疑问:我们知道一般情况下String涉及的字符串处理多数使用indexOf()(可能是考虑效率问题吧),那么这里为什么使用正则呢?我们还是直接看看源码吧:
  public String[] split(String regex, int limit) {
  char ch = 0;
  if (((regex.value.length == 1 &&
  ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) ||
  (regex.length() == 2 &&
  regex.charAt(0) == '\\' &&
  (((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 &&
  ((ch-'a')|('z'-ch)) < 0 &&
  ((ch-'A')|('Z'-ch)) < 0)) &&
  (ch < Character.MIN_HIGH_SURROGATE ||
  ch > Character.MAX_LOW_SURROGATE))
  {
  int off = 0;
  int next = 0;
  boolean limited = limit > 0;
  ArrayList<String> list = new ArrayList<>();
  while ((next = indexOf(ch, off)) != -1) {
  if (!limited || list.size() < limit - 1) {
  list.add(substring(off, next));
  off = next + 1;
  } else { // last one
  //assert (list.size() == limit - 1);
  list.add(substring(off, value.length));
  off = value.length;
  break;
  }
  }
  // If no match was found, return this
  if (off == 0)
  return new String[]{this};
  // Add remaining segment
  if (!limited || list.size() < limit)
  list.add(substring(off, value.length));
  // Construct result
  int resultSize = list.size();
  if (limit == 0)
  while (resultSize > 0 && list.get(resultSize - 1)。length() == 0)
  resultSize--;
  String[] result = new String[resultSize];
  return list.subList(0, resultSize)。toArray(result);
  }
  return Pattern.compile(regex)。split(this, limit);
  }
  可以看到方法内有一个if,如果条件为true,那么就使用indexOf()判断后substring()截取,如果为false,则使用正则处理。那么我们就来分析下这个if的条件:
  //第一步部分:当regex的长度为1且不是".$|()[{^?*+\\"中的时,为真
  (regex.value.length == 1 &&".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1)
  //第二部分:当长度为2时且第一个字符为"\"转义字符,第二个字符不是字符0-9 a-z A-Z 以及utf-16之间的字符
  (regex.length() == 2 && regex.charAt(0) == '\\' && (((
  ch = regex.charAt(1))-'0')|('9'-ch)) < 0 &&
  ((ch-'a')|('z'-ch)) < 0 &&
  ((ch-'A')|('Z'-ch)) < 0)) &&
  (ch < Character.MIN_HIGH_SURROGATE ||
  ch > Character.MAX_LOW_SURROGATE) www.tygj123.com
  从if可以看出如果regex内容为一个非正则匹配符或者是转以后的特殊字符时,采用indexOf()+substring()处理,否则使用正则表达式。
  那么为什么这么做呢,直接使用第一种方法不就行了?其实我们可以考虑一种复杂的情况:
  aaax111xbbbx222xcccx333xddd
  如果我想分割出这样的结果 [aaa, bbb, ccc, ddd] 应该则么做呢?按照第一种方法,实现起来很麻烦,需要一大堆判断,反而不如正则方便,而String中的split()方法正是出于这样的考虑实现的,不信你用split("x.*?x")试试。
  三、启示
  这次这件事虽小,但是却让我收获不少。
  1、使用一个不了解的方法前,一定要看一眼提示,split方法说明里虽然没有明确的提示上述问题,但是多个地方都提到了正则,连参数名字都是regex,作为一个经验丰富的程序员,应该想到这一点。
  2、对于一些小的功能点(往往我们还胸有成竹)一定要写个Test测一下,其实把代码贴过去跑一下费不了多少劲,但是当他淹没在成百上千行的代码中时,想要在发现问题就很费劲了,特别是你不调试根本想不到这点会错 www.yztrans.com
  3、我们在多数项目中都要建个util工具包,封装各种辅助的操作类,然而这些类的功能往往只是满足当时的需求,之后用到类似但有变动的功能时往往习惯单独实现一个,而不是实现一个完善的覆盖原来的,从设计的角度会造成接口不一致:明明同样的需求、同样的参数,我却还要看看他的内部实现才能选择用哪个。对于这些工具类,我们不一定要非常完美,但是应该用心做到尽量完善,这也方便复用。

转载于:https://www.cnblogs.com/haosola/p/3655733.html

String.split()方法你可能不知道的一面相关推荐

  1. Java在使用时需要注意那些问题_java使用String.split方法时要注意的问题

    在使用String.split方法分隔字符串时,分隔符如果用到一些特殊字符,可能会得不到我们预期的结果. 我们看jdk doc中说明 public String[] split(String rege ...

  2. String.split()方法介绍

    String.split()方法我们会经常使用到,这个方法可以将一个字符串分割成数组,但是最近在使用的时候发现一个问题,代码如下: String str1 = "1";String ...

  3. Java String split方法性能分析

    近期笔者分析一段在线代码的性能时,发现Java String类中split()方法的性能和网上一些帖子的描述并不相同,是以记录澄清. Java String split方法到底有没有使用正则表达式? ...

  4. c#中的string.split()方法

    本帖最后由 刘赛 于 2013-4-26 16:32 编辑 C#的String.Split 方法String.Split 方法有6个重载函数: 程序代码 1) public string[] Spli ...

  5. java String split 方法丢弃末尾的空白字符问题

    问题描述 在使用 split 方法时,末尾的空白字符会被丢弃,但是实际上这个行字符可能是一个文件的内容,没个字段内容是否为空都需要记录,此时 split的此无参数方法就不再适用了. 情景再现 Stri ...

  6. 最近遇到一个String.split()方法的坑

    我们的项目数据处理之前需要数据准备,我们把准备好的数据写入txt文件中,然后读取文件,分别处理每一条,我们把读取出来的数据放到Redis中备份一份,当处理到当前条的时候,去Redis中把当前的数据拿出 ...

  7. java诡异的String.split()方法

    Reference https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#split(java.lang.String) 正文 ...

  8. framework 2.0 新增的一个string.split()方法重载

    在1.1版本的时候,出现的split方法只能够使用分隔符分开一个字符串得到一个数组,如果2个分隔符连续的话,那么这个方法会把他解析成一个空字符串在数组中,但是现在的framework2.提供一个重载, ...

  9. 【java】String.split方法limit详解

    regex会切割掉,不会包含在string[]子穿中 API: public String[] split(String regex) public String[] split(String reg ...

最新文章

  1. centos下排查vsftpd出现put零字节问题的记录
  2. Mr. Main and Windmills 模拟,计算几何(昆明)
  3. WORD拼页、书籍折页、反向书籍折页功能(3)
  4. 一文看懂如何搭建AI应用:10周学会深度学习,还赢下5千美元
  5. python引用其他文件提示找不到模块_Python:为什么导入的模块不能引用另一个导入的模块?...
  6. oSIP开发者手册 (四)
  7. VC助手使用问题————all instance of the license* are in use .VA will be disabled
  8. sqoop-import 并行抽数及数据倾斜解决
  9. 这台计算机没有连接到网络怎么办,如果计算机连接到路由器并且没有互联网,该怎么办...
  10. 麻省计算机音乐博士,MIT又一突破!用AI过滤音源,让音乐更悦耳
  11. CAN总线的特点及J1939协议通信原理、内容和应用
  12. IDEA运行java文件环境配置
  13. wps html转换成pdf文件,wps怎么转换成pdf
  14. NFT 数字藏品 3D 展示方案(obj、mtl、png)引用 three.js
  15. Visual Studio Code 基本插件
  16. 比较电路中的正相反馈电阻作用
  17. 车联网通信安全之 SSL/TLS 协议
  18. 一个退休程序员让百年数学难题逼近理论极限
  19. 应用宝使用绑定iOS下载
  20. 场地预约小程序功能有哪些?要怎么做?

热门文章

  1. Spring Ioc源码分析 之 Bean的加载(5):循环依赖处理(populateBean())
  2. 最小生成树与最短路径的区别以及实现方法
  3. java8-接口新特性
  4. 学习使用markdown(markdown篇)
  5. access查询成绩小于5分_又一所大学公布成绩!5个人中有4人专业课130分以上,厉害了!...
  6. Exthereum - 最新开发的以太坊客户端
  7. 总结】Android辅助功能(一)-AccessibilityEvent的分发
  8. win7优化设置_win7优化性能的操作步骤
  9. php代码文本型怎么更改成数值型,php 怎么将字符转成数字
  10. php nginx exec kill,彻底杀死nginx并重启