上一节我们主要讲了String类的一些不是很常用的方法,其中需要掌握的如下,我就不再赘述了

  1. public int length()
  2. public boolean isEmpty()
  3. public byte[] getBytes()
  4. public byte[] getBytes(String charsetName)
  5. public char charAt(int index)
  6. public boolean equals(Object anObject)
  7. public boolean equalsIgnoreCase(String anotherString)

  继续今天的内容

  1. /*
  2. * String实现接口Comparable中的compareTo方法,通过源码我们可以看出s1.compareTo(s2)依次拿出s1和s2的第k个字符进行比较
  3. * 如果某两个不相等,则返回这两个字符的差:c1-c2(ps:这里你需要知道java中byte、short、char在参与运算的时候将自动转换为int类型,所以最后返回的是int类型)
  4. * 最后我们得出结论:
  5. * 返回值是0,则两个字符串相等
  6. */
  7. public int compareTo(String anotherString) {
  8. int len1 = value.length;
  9. int len2 = anotherString.value.length;
  10. int lim = Math.min(len1, len2);
  11. char v1[] = value;
  12. char v2[] = anotherString.value;
  13.  
  14. int k = 0;
  15. while (k < lim) {
  16. char c1 = v1[k];
  17. char c2 = v2[k];
  18. if (c1 != c2) {
  19. return c1 - c2;
  20. }
  21. k++;
  22. }
  23. return len1 - len2;
  24. }
  25.  
  26. /*
  27. * Comparator是一个比较器,String采用成员内部类的形式定义了一个比较器,comparator和comparable一时半会也讲不清楚
  28. * 这里你只需要知道二者都是用于比较的,comparable比较的是自然排序(其实所谓的自然排序也是程序猿规定好的),比较简单,大部分是内置的,比如说String和Integer等类都有
  29. * 而comparator是比较一些 比较复杂的,用户自己定义的,比如说下面的不区分大小写的比较就是用comparator实现的。仔细看源代码很简单的。
  30. */
  31. public static final Comparator<String> CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator();
  32.  
  33. private static class CaseInsensitiveComparator implements Comparator<String>, java.io.Serializable {
  34. // use serialVersionUID from JDK 1.2.2 for interoperability
  35. private static final long serialVersionUID = 8575799808933029326L;
  36.  
  37. public int compare(String s1, String s2) {
  38. int n1 = s1.length();
  39. int n2 = s2.length();
  40. int min = Math.min(n1, n2);
  41. for (int i = 0; i < min; i++) {
  42. char c1 = s1.charAt(i);
  43. char c2 = s2.charAt(i);
  44. if (c1 != c2) {
  45. c1 = Character.toUpperCase(c1);
  46. c2 = Character.toUpperCase(c2);
  47. if (c1 != c2) {
  48. c1 = Character.toLowerCase(c1);
  49. c2 = Character.toLowerCase(c2);
  50. if (c1 != c2) {
  51. // No overflow because of numeric promotion
  52. return c1 - c2;
  53. }
  54. }
  55. }
  56. }
  57. return n1 - n2;
  58. }
  59.  
  60. //替换反序列化的对象
  61. private Object readResolve() {
  62. return CASE_INSENSITIVE_ORDER;
  63. }
  64. }
  65.  
  66. /*
  67. * String的另一个比较,也就是不区分大小写的比较,内部封装着comparator的实现类的对象
  68. *
  69. * 总结:String有两种比较方式
  70. * 1.compareTo 按照自然顺序比较,区分大小写
  71. * 2.compareToIgnoreCase 不区分大小写的比较
  72. * 虽然二者方法名很像,但是实现原理完全不一样!!!!
  73. */
  74. public int compareToIgnoreCase(String str) {
  75. return CASE_INSENSITIVE_ORDER.compare(this, str);
  76. }
  77.  
  78. /*
  79. * 测试两个字符串区域是否相等,还记得吗?equalsIgnoreCase方法的内部其实使用的就是regionMatches
  80. */
  81. public boolean regionMatches(int toffset, String other, int ooffset, int len) {
  82. char ta[] = value;
  83. int to = toffset;
  84. char pa[] = other.value;
  85. int po = ooffset;
  86. // Note: toffset, ooffset, or len might be near -1>>>1.
  87. if ((ooffset < 0) || (toffset < 0) || (toffset > (long) value.length - len)
  88. || (ooffset > (long) other.value.length - len)) {
  89. return false;
  90. }
  91. while (len-- > 0) {
  92. if (ta[to++] != pa[po++]) {
  93. return false;
  94. }
  95. }
  96. return true;
  97. }
  98.  
  99. /*
  100. *
  101. */
  102. public boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) {
  103. char ta[] = value;
  104. int to = toffset;
  105. char pa[] = other.value;
  106. int po = ooffset;
  107. // Note: toffset, ooffset, or len might be near -1>>>1.
  108. if ((ooffset < 0) || (toffset < 0) || (toffset > (long) value.length - len)
  109. || (ooffset > (long) other.value.length - len)) {
  110. return false;
  111. }
  112. while (len-- > 0) {
  113. char c1 = ta[to++];
  114. char c2 = pa[po++];
  115. if (c1 == c2) {
  116. continue;
  117. }
  118. if (ignoreCase) {
  119.  
  120. char u1 = Character.toUpperCase(c1);
  121. char u2 = Character.toUpperCase(c2);
  122. if (u1 == u2) {
  123. continue;
  124. }
  125.  
  126. if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
  127. continue;
  128. }
  129. }
  130. return false;
  131. }
  132. return true;
  133. }
  134.  
  135. /*
  136. * 从字符串开始位置toffset去匹配目标字符串prefix,很常用的方法,代码原理很简单
  137. * startsWith(String prefix, int toffset)
  138. * startsWith(String prefix)
  139. * endsWith(String prefix)
  140. */
  141. public boolean startsWith(String prefix, int toffset) {
  142. char ta[] = value;
  143. int to = toffset;
  144. char pa[] = prefix.value;
  145. int po = 0;
  146. int pc = prefix.value.length;
  147. // Note: toffset might be near -1>>>1.
  148. if ((toffset < 0) || (toffset > value.length - pc)) {
  149. return false;
  150. }
  151. while (--pc >= 0) {
  152. if (ta[to++] != pa[po++]) {
  153. return false;
  154. }
  155. }
  156. return true;
  157. }
  158.  
  159. public boolean startsWith(String prefix) {
  160. return startsWith(prefix, 0);
  161. }
  162.  
  163. public boolean endsWith(String suffix) {
  164. return startsWith(suffix, value.length - suffix.value.length);
  165. }
  166.  
  167. /*
  168. * String重写了equals,也重写了hashCode,这里我解释一下Object中的hashCode返回的是什么,因为是原生方法,所以源代码当中并没有
  169. * 但是自己去试试就知道是什么了,创建一个类(不重写hashCode)并实例化,输出的是一个int类型的,然后重写再输出得到的还是相同长度的int类型,
  170. *
  171. */
  172. public int hashCode() {
  173. int h = hash;
  174. if (h == 0 && value.length > 0) {
  175. char val[] = value;
  176.  
  177. for (int i = 0; i < value.length; i++) {
  178. h = 31 * h + val[i];
  179. }
  180. hash = h;
  181. }
  182. return h;
  183. }

java源码解析之String类(三)的更多相关文章

  1. java源码解析之String类(一)

    String是我们接触最多的类,无论是学习中还是工作中,基本每天都会和字符串打交道,从字符串本身的各种拼接.切片.变形,再到和其他基本数据类型的转换,几乎无时无刻都在使用它,今天就让我们揭开Strin ...

  2. java源码解析之String类(二)

    上一节主要介绍了String类的一些构造方法,主要分为四类 无参构造器:String(),创建一个空字符串"",区别于null字符串,""已经初始化,null并 ...

  3. java源码解析之String类(四)

    /* * 返回指定字符第一次出现的字符串内的索引 */ public int indexOf(int ch) { return indexOf(ch, 0); } /* * 返回指定字符第一次出现的字 ...

  4. java源码解析之String类(五)

    /* * 切片函数,非常重要,这里一定要牢记beginIndex是开始位置,endIndex是结束位置,区别于以前学的offset是开始位置,而count或length是个数和长度 * 比如说,new ...

  5. Java源码解析——集合框架(三)——Vector

    Vector源码解析 首先说一下Vector和ArrayList的区别: (1) Vector的所有方法都是有synchronized关键字的,即每一个方法都是同步的,所以在使用起来效率会非常低,但是 ...

  6. java源码解析之Object类

    一.Object类概述   Object类是java中类层次的根,是所有类的基类.在编译时会自动导入.Object中的方法如下: 二.方法详解   Object的方法可以分成两类,一类是被关键字fin ...

  7. TiKV 源码解析系列文章(三)Prometheus(上)

    本文为 TiKV 源码解析系列的第三篇,继续为大家介绍 TiKV 依赖的周边库 rust-prometheus,本篇主要介绍基础知识以及最基本的几个指标的内部工作机制,下篇会介绍一些高级功能的实现原理 ...

  8. [Java源码解析] -- String类的compareTo(String otherString)方法的源码解析

    String类下的compareTo(String otherString)方法的源码解析 一. 前言 近日研究了一下String类的一些方法, 通过查看源码, 对一些常用的方法也有了更透彻的认识,  ...

  9. 【Java源码解析】Thread

    简介 线程本质上也是进程.线程机制提供了在同一程序内共享内存地址空间运行的一组线程.对于内核来讲,它就是进程,只是该进程和其他一下进程共享某些资源,比如地址空间.在Java语言里,Thread类封装了 ...

随机推荐

  1. Qt5官方demo解析集35——Music Player(使用winextras模块)

    本系列所有文章可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集34——Concentr ...

  2. Viewport3D中的摄像机(二、摄像机动作)

    原文:Viewport3D中的摄像机(二.摄像机动作) 前文介绍了Viewport3D中的两种摄像机:OrthographicCamera和PerspectiveCamera.在3D场景里漫游,最主要 ...

  3. ASP.NET Core 视图 - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core 视图 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 视图 花了几章节,终于把 ASP.NET Core MVC 中的 C 控 ...

  4. BigTable读后笔记

    BigTable读后笔记 GFS可能出现重复记录或者padding,Bigtable如何处理这种情况使得对外提供强一致性模型? ANS: Bigtable写入GFS的数据分为两种: 1)操作日志,当T ...

  5. GTK+浅谈之一Windows10下QtCreator中GTK+环境搭建(十几篇)

    一.简介 虽然GTK+是Linux下的开发环境,因为其跨平台特性,有时候需要在Windows上用到它的.如下是在Windows10下配置GTK+的开发环境.        Gnome的开发基础结构是围 ...

  6. .net reactor 学习系列(三)---.net reactor代码自动操作相关保护功能

    原文:.net reactor 学习系列(三)---.net reactor代码自动操作相关保护功能         接上篇,上篇已经学习了界面的各种功能以及各种配置,这篇准备学习下代码控制许可证. ...

  7. spring boot 配置swagger UI

    springboot集成swaggerUI 有这样的需求 1.在每个接口上都增加一个字段: 2.接口文档只展示满足一定条件URL的接口 配置文件 详细看代码 import org.springfram ...

  8. Nginx之Eclipse开发环境配置

    C开发的IDE很多,为什么使用Eclipse?原因: 1. 历史原因:使用eclipse时间长,比较熟悉. 2. 功能原因:使用eclipse查看源码,可以在各个函数与头文件间直接跳转.这是所谓号称& ...

  9. 毫秒数据字符串转换为DateTime

    思路:取出毫秒结果,在1970年1月1日 00:00:00的基础上,加上毫秒数 string date = "/Date(1486363695453)/"; date = date ...

  10. XF警告试图

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...