概述

CharMatcher提供了多种对字符串处理的方法, 它的主要意图有:

1. 找到匹配的字符

2. 处理匹配的字符

CharMatcher内部主要实现包括两部分:

1. 实现了大量公用内部类, 用来方便用户对字符串做匹配: 例如 JAVA_DIGIT 匹配数字, JAVA_LETTER 匹配字母等等.

2. 实现了大量处理字符串的方法, 使用特定的CharMatcher可以对匹配到的字符串做出多种处理, 例如 remove(), replace(), trim(), retain()等等

CharMatcher本身是一个抽象类, 其中一些操作方法是抽象方法, 他主要依靠内部继承CharMatcher的内部子类来实现抽象方法和重写一些操作方法, 因为不同的匹配规则的这些操作方法具有不同的实现要求

常用方法介绍

默认实现类

CharMatcher本身提供了很多CharMatcher实现类,如下:

ANY: 匹配任何字符

ASCII: 匹配是否是ASCII字符

BREAKING_WHITESPACE: 匹配所有可换行的空白字符(不包括非换行空白字符,例如"\u00a0")

DIGIT: 匹配ASCII数字

INVISIBLE: 匹配所有看不见的字符

JAVA_DIGIT: 匹配UNICODE数字, 使用 Character.isDigit() 实现

JAVA_ISO_CONTROL: 匹配ISO控制字符, 使用 Charater.isISOControl() 实现

JAVA_LETTER: 匹配字母, 使用 Charater.isLetter() 实现

JAVA_LETTER_OR_DIGET: 匹配数字或字母

JAVA_LOWER_CASE: 匹配小写

JAVA_UPPER_CASE: 匹配大写

NONE: 不匹配所有字符

SINGLE_WIDTH: 匹配单字宽字符, 如中文字就是双字宽

WHITESPACE: 匹配所有空白字符

常用操作方法

CharMatcher is(char match): 返回匹配指定字符的Matcher

CharMatcher isNot(char match): 返回不匹配指定字符的Matcher

CharMatcher anyOf(CharSequence sequence): 返回匹配sequence中任意字符的Matcher

CharMatcher noneOf(CharSequence sequence): 返回不匹配sequence中任何一个字符的Matcher

CharMatcher inRange(char startInclusive, char endIncludesive): 返回匹配范围内任意字符的Matcher

CharMatcher forPredicate(Predicate<? super Charater> predicate): 返回使用predicate的apply()判断匹配的Matcher

CharMatcher negate(): 返回以当前Matcher判断规则相反的Matcher

CharMatcher and(CharMatcher other): 返回与other匹配条件组合做与来判断的Matcher

CharMatcher or(CharMatcher other): 返回与other匹配条件组合做或来判断的Matcher

boolean matchesAnyOf(CharSequence sequence): 只要sequence中有任意字符能匹配Matcher,返回true

boolean matchesAllOf(CharSequence sequence): sequence中所有字符都能匹配Matcher,返回true

boolean matchesNoneOf(CharSequence sequence): sequence中所有字符都不能匹配Matcher,返回true

int indexIn(CharSequence sequence): 返回sequence中匹配到的第一个字符的坐标

int indexIn(CharSequence sequence, int start): 返回从start开始,在sequence中匹配到的第一个字符的坐标

int lastIndexIn(CharSequence sequence): 返回sequence中最后一次匹配到的字符的坐标

int countIn(CharSequence sequence): 返回sequence中匹配到的字符计数

String removeFrom(CharSequence sequence): 删除sequence中匹配到到的字符并返回

String retainFrom(CharSequence sequence): 保留sequence中匹配到的字符并返回

String replaceFrom(CharSequence sequence, char replacement): 替换sequence中匹配到的字符并返回

String trimFrom(CharSequence sequence): 删除首尾匹配到的字符并返回

String trimLeadingFrom(CharSequence sequence): 删除首部匹配到的字符

String trimTrailingFrom(CharSequence sequence): 删除尾部匹配到的字符

String collapseFrom(CharSequence sequence, char replacement): 将匹配到的组(连续匹配的字符)替换成replacement

String trimAndCollapseFrom(CharSequence sequence, char replacement): 先trim在replace

部分实现源码介绍

下面对CharMatcher的常用的操作方法实现做一些介绍

  1. /**
  2. * 返回一个与当前Matcher匹配规则相反的Matcher
  3. */
  4. public CharMatcher negate() {
  5. final CharMatcher original = this;
  6. return new CharMatcher(original + ".negate()") {
  7. @Override public boolean matches(char c) {
  8. return !original.matches(c);
  9. }
  10.  
  11. @Override public boolean matchesAllOf(CharSequence sequence) {
  12. return original.matchesNoneOf(sequence);
  13. }
  14.  
  15. @Override public boolean matchesNoneOf(CharSequence sequence) {
  16. return original.matchesAllOf(sequence);
  17. }
  18.  
  19. @Override public int countIn(CharSequence sequence) {
  20. return sequence.length() - original.countIn(sequence);
  21. }
  22.  
  23. @Override public CharMatcher negate() {
  24. return original;
  25. }
  26. };
  27. }
  28.  
  29. /**
  30. * 返回一个具有组合规则链的Matcher
  31. */
  32. public CharMatcher and(CharMatcher other) {
  33. return new And(this, checkNotNull(other));
  34. }
  35.  
  36. /**
  37. * And的实现和Ordering的Compound是一样的
  38. * 使用一个内部子类继承Matcher,然后内部使用组合的方式将
  39. * 多个Matcher组合在一起,调用操作方法的时候依次调用这些
  40. * Matcher的同名操作方法即可
  41. */
  42. private static class And extends CharMatcher {
  43. final CharMatcher first;
  44. final CharMatcher second;
  45.  
  46. And(CharMatcher a, CharMatcher b) {
  47. this(a, b, "CharMatcher.and(" + a + ", " + b + ")");
  48. }
  49.  
  50. And(CharMatcher a, CharMatcher b, String description) {
  51. super(description);
  52. first = checkNotNull(a);
  53. second = checkNotNull(b);
  54. }
  55.  
  56. @Override
  57. public CharMatcher and(CharMatcher other) {
  58. return new And(this, other);
  59. }
  60.  
  61. @Override
  62. public boolean matches(char c) {
  63. return first.matches(c) && second.matches(c);
  64. }
  65.  
  66. @Override
  67. CharMatcher withToString(String description) {
  68. return new And(first, second, description);
  69. }
  70. }
  71.  
  72. /**
  73. * Or的实现与And一样,不再赘述
  74. */
  75. public CharMatcher or(CharMatcher other) {
  76. return new Or(this, checkNotNull(other));
  77. }
  78.  
  79. private static class Or extends CharMatcher {
  80. final CharMatcher first;
  81. final CharMatcher second;
  82.  
  83. Or(CharMatcher a, CharMatcher b, String description) {
  84. super(description);
  85. first = checkNotNull(a);
  86. second = checkNotNull(b);
  87. }
  88.  
  89. Or(CharMatcher a, CharMatcher b) {
  90. this(a, b, "CharMatcher.or(" + a + ", " + b + ")");
  91. }
  92.  
  93. @Override
  94. public CharMatcher or(CharMatcher other) {
  95. return new Or(this, checkNotNull(other));
  96. }
  97.  
  98. @Override
  99. public boolean matches(char c) {
  100. return first.matches(c) || second.matches(c);
  101. }
  102.  
  103. @Override
  104. CharMatcher withToString(String description) {
  105. return new Or(first, second, description);
  106. }
  107. }
  108.  
  109. /**
  110. * Returns a {@code char} matcher functionally equivalent to this one, but which may be faster to
  111. * query than the original; your mileage may vary. Precomputation takes time and is likely to be
  112. * worthwhile only if the precomputed matcher is queried many thousands of times.
  113. *
  114. * <p>This method has no effect (returns {@code this}) when called in GWT: it's unclear whether a
  115. * precomputed matcher is faster, but it certainly consumes more memory, which doesn't seem like a
  116. * worthwhile tradeoff in a browser.
  117. */
  118. public CharMatcher precomputed() {
  119. return Platform.precomputeCharMatcher(this);
  120. }
  121.  
  122. /**
  123. * 使用最慢的方式来返回字符全集中所有能被Matcher匹配的字符
  124. * 最慢的方式?!
  125. */
  126. char[] slowGetChars() {
  127. char[] allChars = new char[65536];
  128. int size = 0;
  129. for (int c = Character.MIN_VALUE; c <= Character.MAX_VALUE; c++) {
  130. if (matches((char) c)) {
  131. allChars[size++] = (char) c;
  132. }
  133. }
  134. char[] retValue = new char[size];
  135. System.arraycopy(allChars, 0, retValue, 0, size);
  136. return retValue;
  137. }
  138.  
  139. /**
  140. * 只要sequence有任意字符匹配Matcher,则返回true
  141. */
  142. public boolean matchesAnyOf(CharSequence sequence) {
  143. return !matchesNoneOf(sequence);
  144. }
  145.  
  146. /**
  147. * 如果sequence所有字符都匹配Matcher,则返回true
  148. */
  149. public boolean matchesAllOf(CharSequence sequence) {
  150. for (int i = sequence.length() - 1; i >= 0; i--) {
  151. if (!matches(sequence.charAt(i))) {
  152. return false;
  153. }
  154. }
  155. return true;
  156. }
  157.  
  158. /**
  159. * 如果sequence所有字符都不匹配Matcher,则返回true
  160. */
  161. public boolean matchesNoneOf(CharSequence sequence) {
  162. return indexIn(sequence) == -1;
  163. }
  164.  
  165. /**
  166. * 返回Matcher在sequence中匹配到的第一个字符的坐标
  167. * 没有匹配则返回 -1
  168. */
  169. public int indexIn(CharSequence sequence) {
  170. int length = sequence.length();
  171. for (int i = 0; i < length; i++) {
  172. if (matches(sequence.charAt(i))) {
  173. return i;
  174. }
  175. }
  176. return -1;
  177. }
  178.  
  179. /**
  180. * 返回Matcher在sequence中从start开始的匹配到的第一个字符的坐标
  181. */
  182. public int indexIn(CharSequence sequence, int start) {
  183. int length = sequence.length();
  184. Preconditions.checkPositionIndex(start, length);
  185. for (int i = start; i < length; i++) {
  186. if (matches(sequence.charAt(i))) {
  187. return i;
  188. }
  189. }
  190. return -1;
  191. }
  192.  
  193. /**
  194. * 返回sequence最后一次匹配到Matcher的坐标
  195. */
  196. public int lastIndexIn(CharSequence sequence) {
  197. for (int i = sequence.length() - 1; i >= 0; i--) {
  198. if (matches(sequence.charAt(i))) {
  199. return i;
  200. }
  201. }
  202. return -1;
  203. }
  204.  
  205. /**
  206. * 返回Sequence匹配到Matcher的次数
  207. */
  208. public int countIn(CharSequence sequence) {
  209. int count = 0;
  210. for (int i = 0; i < sequence.length(); i++) {
  211. if (matches(sequence.charAt(i))) {
  212. count++;
  213. }
  214. }
  215. return count;
  216. }
  217.  
  218. /**
  219. * 删除sequence中匹配到的所有字符并返回
  220. */
  221. @CheckReturnValue
  222. public String removeFrom(CharSequence sequence) {
  223. String string = sequence.toString();
  224. int pos = indexIn(string);
  225. if (pos == -1) {
  226. return string;
  227. }
  228.  
  229. char[] chars = string.toCharArray();
  230. int spread = 1;
  231.  
  232. // This unusual loop comes from extensive benchmarking
  233. // 位移删除算法, 使用了双层循环和break OUT 写法
  234. OUT: while (true) {
  235. pos++;
  236. while (true) {
  237. if (pos == chars.length) {
  238. break OUT;
  239. }
  240. if (matches(chars[pos])) {
  241. break;
  242. }
  243. chars[pos - spread] = chars[pos];
  244. pos++;
  245. }
  246. spread++;
  247. }
  248. return new String(chars, 0, pos - spread);
  249. }
  250.  
  251. /**
  252. * 保留所有匹配的Matcher的字符并返回
  253. * 使用逆向的Matcher的removeFrom()实现
  254. */
  255. @CheckReturnValue
  256. public String retainFrom(CharSequence sequence) {
  257. return negate().removeFrom(sequence);
  258. }
  259.  
  260. /**
  261. * 将所有匹配到Matcher的字符换成指定字符
  262. */
  263. @CheckReturnValue
  264. public String replaceFrom(CharSequence sequence, char replacement) {
  265. String string = sequence.toString();
  266. int pos = indexIn(string);
  267. if (pos == -1) {
  268. return string;
  269. }
  270. char[] chars = string.toCharArray();
  271. chars[pos] = replacement;
  272. for (int i = pos + 1; i < chars.length; i++) {
  273. if (matches(chars[i])) {
  274. chars[i] = replacement;
  275. }
  276. }
  277. return new String(chars);
  278. }
  279.  
  280. /**
  281. * 将所有可以匹配到的字符换成指定字符串
  282. * 他的实现与替换成字符不相同,他是使用indexIn和StringBuilder实现的
  283. */
  284. @CheckReturnValue
  285. public String replaceFrom(CharSequence sequence, CharSequence replacement) {
  286. int replacementLen = replacement.length();
  287. if (replacementLen == 0) {
  288. return removeFrom(sequence);
  289. }
  290. if (replacementLen == 1) {
  291. return replaceFrom(sequence, replacement.charAt(0));
  292. }
  293.  
  294. String string = sequence.toString();
  295. int pos = indexIn(string);
  296. if (pos == -1) {
  297. return string;
  298. }
  299.  
  300. int len = string.length();
  301. StringBuilder buf = new StringBuilder((len * 3 / 2) + 16);
  302.  
  303. int oldpos = 0;
  304. do {
  305. buf.append(string, oldpos, pos);
  306. buf.append(replacement);
  307. oldpos = pos + 1;
  308. pos = indexIn(string, oldpos);
  309. } while (pos != -1);
  310.  
  311. buf.append(string, oldpos, len);
  312. return buf.toString();
  313. }
  314.  
  315. /**
  316. * 去除sequence首尾所有这个Matcher匹配的字符
  317. */
  318. @CheckReturnValue
  319. public String trimFrom(CharSequence sequence) {
  320. int len = sequence.length();
  321. int first;
  322. int last;
  323.  
  324. for (first = 0; first < len; first++) {
  325. if (!matches(sequence.charAt(first))) {
  326. break;
  327. }
  328. }
  329. for (last = len - 1; last > first; last--) {
  330. if (!matches(sequence.charAt(last))) {
  331. break;
  332. }
  333. }
  334.  
  335. return sequence.subSequence(first, last + 1).toString();
  336. }
  337.  
  338. /**
  339. * 去掉sequence开头的所有Matcher能匹配的字符
  340. */
  341. @CheckReturnValue
  342. public String trimLeadingFrom(CharSequence sequence) {
  343. int len = sequence.length();
  344. int first;
  345.  
  346. for (first = 0; first < len; first++) {
  347. if (!matches(sequence.charAt(first))) {
  348. break;
  349. }
  350. }
  351.  
  352. return sequence.subSequence(first, len).toString();
  353. }
  354.  
  355. /**
  356. * 删除字符串尾部所有能匹配Matcher的字符
  357. */
  358. @CheckReturnValue
  359. public String trimTrailingFrom(CharSequence sequence) {
  360. int len = sequence.length();
  361. int last;
  362.  
  363. for (last = len - 1; last >= 0; last--) {
  364. if (!matches(sequence.charAt(last))) {
  365. break;
  366. }
  367. }
  368.  
  369. return sequence.subSequence(0, last + 1).toString();
  370. }
  371.  
  372. /**
  373. * 将所有能被Matcher匹配的组(连续匹配的字串)替换成指定字符
  374. */
  375. @CheckReturnValue
  376. public String collapseFrom(CharSequence sequence, char replacement) {
  377. int first = indexIn(sequence);
  378. if (first == -1) {
  379. return sequence.toString();
  380. }
  381.  
  382. // TODO(kevinb): see if this implementation can be made faster
  383. StringBuilder builder = new StringBuilder(sequence.length())
  384. .append(sequence.subSequence(0, first))
  385. .append(replacement);
  386. boolean in = true;
  387. for (int i = first + 1; i < sequence.length(); i++) {
  388. char c = sequence.charAt(i);
  389. if (matches(c)) {
  390. if (!in) {
  391. builder.append(replacement);
  392. in = true;
  393. }
  394. } else {
  395. builder.append(c);
  396. in = false;
  397. }
  398. }
  399. return builder.toString();
  400. }
  401.  
  402. /**
  403. * 先trim再Collapse
  404. */
  405. @CheckReturnValue
  406. public String trimAndCollapseFrom(CharSequence sequence, char replacement) {
  407. int first = negate().indexIn(sequence);
  408. if (first == -1) {
  409. return ""; // everything matches. nothing's left.
  410. }
  411. StringBuilder builder = new StringBuilder(sequence.length());
  412. boolean inMatchingGroup = false;
  413. for (int i = first; i < sequence.length(); i++) {
  414. char c = sequence.charAt(i);
  415. if (matches(c)) {
  416. inMatchingGroup = true;
  417. } else {
  418. if (inMatchingGroup) {
  419. builder.append(replacement);
  420. inMatchingGroup = false;
  421. }
  422. builder.append(c);
  423. }
  424. }
  425. return builder.toString();
  426. }
  427.  
  428. // Predicate interface
  429.  
  430. /**
  431. * matches()的异名方法
  432. */
  433. @Override public boolean apply(Character character) {
  434. return matches(character);
  435. }

补完:

1. 提供的默认实现CharMatcher功能及介绍

2. 操作方法签名及功能列表

3. 使用代码示例

Guava CharMatcher的更多相关文章

  1. 使用 Google Guava 美化你的 Java 代码

    文章转载自:http://my.oschina.net/leejun2005/blog/172328 目录:[ - ] 1-使用 GOOGLE COLLECTIONS,GUAVA,STATIC IMP ...

  2. Guava 教程2-深入探索 Google Guava 库

    原文出处: oschina 在这个系列的第一部分里,我简单的介绍了非常优秀的Google collections和Guava类库,并简要的解释了作为Java程序员,如果使用Guava库来减少项目中大量 ...

  3. Guava入门使用教程

    Guava入门使用教程 Guava Maven dependency In our examples, we use the following Maven dependency. <depen ...

  4. guava(三)字符串处理 Joiner Splitter CharMatcher

    一.Joiner 拼接字符串 1.join 拼接集合中的元素 System.out.println(Joiner.on(";").join(Ints.asList(1,2,3))) ...

  5. Guava库介绍之实用工具类

    作者:Jack47 转载请保留作者和原文出处 欢迎关注我的微信公众账号程序员杰克,两边的文章会同步,也可以添加我的RSS订阅源. 本文是我写的Google开源的Java编程库Guava系列之一,主要介 ...

  6. Google Java编程库Guava介绍

    本系列想介绍下Java下开源的优秀编程库--Guava[ˈgwɑːvə].它包含了Google在Java项目中使用一些核心库,包含集合(Collections),缓存(Caching),并发编程库(C ...

  7. guava函数式编程

    [Google Guava] 4-函数式编程 原文链接 译文链接 译者:沈义扬,校对:丁一 注意事项 截至JDK7,Java中也只能通过笨拙冗长的匿名类来达到近似函数式编程的效果.预计JDK8中会有所 ...

  8. guava常用操作

    Jack47 我思故我在 Google Java编程库Guava介绍 本系列想介绍下Java下开源的优秀编程库--Guava[ˈgwɑːvə].它包含了Google在Java项目中使用一些核心库,包含 ...

  9. Guava 9-I/O

    字节流和字符流 Guava使用术语”流” 来表示可关闭的,并且在底层资源中有位置状态的I/O数据流.术语”字节流”指的是InputStream或OutputStream,”字符流”指的是Reader ...

随机推荐

  1. HTML5 标签语法变化和使用概念

    1.H5与H4的区别 概念的变化: H5更注重内容与结构,不再只专注于表现. 声明与标签: 新的声明背简化: <!DOCTYPE html> <meta charset=utf-8& ...

  2. React Native之原生模块的开发(Android)学习笔记

      目录 1.为什么我们需要原生模块开发 2.开发Android原生模块的主要流程 3.原生模块开发实战   1.为什么我们需要原生模块开发? 我们在用RN开发App的时候,有时候需要用到一些原生模块 ...

  3. vue打包以及在Apache环境下的配置

    vue打包,我们都清楚,实在记不住命令的可以去package.json中看: npm run build 打包后会生成dist文件夹,将dist文件夹下的所有文件复制到Apache下的www的文件夹下 ...

  4. 当Java遇到XML 的邂逅+dom4j

    XML简介: XML:可扩展标记语言! 01.很象html 02.着重点是数据的保存 03.无需预编译 04.符合W3C标准 可扩展:我们可以自定义,完全按照自己的规则来! 标记: 计算机所能认识的信 ...

  5. odoo视图继承

    odoo视图继承 简介继承 在odoo里可以通过继承的方式来改写已经存在的view 对比view的定义视图定义中写法多了inherit_id inherit_id指向要改写的view <fiel ...

  6. 干货: 可视化项目实战经验分享,轻松玩转 Bokeh (建议收藏)

    作者 | Will Koehrsen 翻译 | Lemon 译文出品 | Python数据之道 (ID:PyDataRoad) 本文通过一个项目案例,详细的介绍了如何从 Bokeh 基础到构建 Bok ...

  7. Android - Base64

    Android 将图片转换为Base64 public void convertToBase64(View view) throws IOException { //获取ImageView的图片 Bi ...

  8. 八. Pandas的轴

    axis=0代表跨行(down),而axis=1代表跨列(across) 使用0值表示沿着每一列或行标签\索引值向下执行方法 使用1值表示沿着每一行或者列标签模向执行对应的方法 下图代表在DataFr ...

  9. codevs 2821 天使之城

    题目描述 Description 天使城有一个火车站,每辆火车都从A方向驶入车站,再从B方向驶出车站. 为了调度火车,火车站设有停放轨道,可存放5辆火车.已知从A进入车站顺序为1.2.3…….现在给你 ...

  10. Linux学习笔记04—IP配置

    一.自动获取IP只有一种情况可以自动获取IP地址,那就是你的Linux所在的网络环境中有DHCP服务.只要你的真机可以自动获取IP,那么安装在虚拟机的Linux同样也可以自动获取IP. 方法很简单,只 ...