Java反转字符串和相关字符编码问题

2023-11-07

    反转字符串一直被当作是简单问题,大家的思想主要就是利用遍历,首尾交换字符实现字符串的反转。例如下面的代码,就可以简单实现反转。

 
 

 
  
1 public String reverse( char [] value){
2 for ( int i = (value.length - 1 ) >> 1 ; i >= 0 ; i -- ){
3 char temp = value[i];
4 value[i] = value[value.length - 1 - i];
5 value[value.length - 1 - i] = temp;
6 }
7 return new String(value);
8 }
9
10  

 

    这样的代码,在算法方面是没有任何问题的。但是今天在查看StringBuffer源代码的时候发现,其中reverse方法的源代码写的很精妙。源代码如下:

 
  
1 public AbstractStringBuilder reverse() {
2 boolean hasSurrogate = false ;
3 int n = count - 1 ;
4 for ( int j = (n - 1 ) >> 1 ; j >= 0 ; -- j) {
5 char temp = value[j];
6 char temp2 = value[n - j];
7 if ( ! hasSurrogate) {
8 hasSurrogate = (temp >= Character.MIN_SURROGATE && temp <= Character.MAX_SURROGATE)
9 || (temp2 >= Character.MIN_SURROGATE && temp2 <= Character.MAX_SURROGATE);
10 }
11 value[j] = temp2;
12 value[n - j] = temp;
13 }
14 if (hasSurrogate) {
15 // Reverse back all valid surrogate pairs
16   for ( int i = 0 ; i < count - 1 ; i ++ ) {
17 char c2 = value[i];
18 if (Character.isLowSurrogate(c2)) {
19 char c1 = value[i + 1 ];
20 if (Character.isHighSurrogate(c1)) {
21 value[i ++ ] = c1;
22 value[i] = c2;
23 }
24 }
25 }
26 }
27 return this ;
28 }
29  

 

 

    这个方法是定义在StringBuffer的父类AbstractStringBuilder中的,所以该方法的返回值是AbstractStringBuilder,在子类中调用的方式如下:

 
  
1 public synchronized StringBuffer reverse() {
2 super .reverse();
3 return this ;
4 }

 

    从方法的内容来看,源代码中的基本思路是一致的,同样采用遍历一半字符串,然后将每个字符与其对应的字符进行交换。但是有不同之处,就是要判断每个字符是否在Character.MIN_SURROGATE(\ud800)Character.MAX_SURROGATE(\udfff)之间。如果发现整个字符串中含有这种情况,则再次从头至尾遍历一次,同时判断value[i]是否满足Character.isLowSurrogate(),如果满足的情况下,继续判断value[i+1]是否满足Character.isHighSurrogate(),如果也满足这种情况,则将第i位和第i+1位的字符互换。可能有的人会疑惑,为什么要这么做,因为Java中的字符已经采用Unicode代码,每个字符可以放下一个汉字。为什么还要这么做?

    一个完整的 Unicode 字符叫代码点CodePoint,而一个 Java char 代码单元 code unit。String 对象以UTF-16保存 Unicode 字符,需要用2个字符表示一个超大字符集的汉字,这这种表示方式称之为 Surrogate,第一个字符叫 Surrogate High,第二个就是 Surrogate Low。具体需要注意的事宜如下:

  1. 判断一个char是否是Surrogate区的字符,用Character isHighSurrogate()/isLowSurrogate()方法即可判断。从两个Surrogate High/Low 字符,返回一个完整的 Unicode CodePoint Character.toCodePoint()/codePointAt()方法。

  2.   一个Code Point,可能需要一个也可能需要两个char表示,因此不能直接使用 CharSequence.length()方法直接返回一个字符串到底有多少个汉字,而需要用String.codePointCount()/Character.codePointCount()

  3.  要定位字符串中的第N个字符,不能直接将N作为偏移量,而需要从字符串头部依次遍历得到,需要用String/Character.offsetByCodePoints() 方法。

  4. 从字符串的当前字符,找到上一个字符,也不能直接用offset-- 实现,而需要用 String.codePointBefore()/Character.codePointBefore(),或用 String/Character.offsetByCodePoints()

  5.  从当前字符,找下一个字符,不能直接用 offset++实现,需要判断当前 CodePoint的长度后,再计算得到,或用String/Character.offsetByCodePoints()

关于字符详细说明,请查看http://www.cnblogs.com/wanlipeng/archive/2011/01/27/1946435.html

转载于:https://www.cnblogs.com/wanlipeng/archive/2011/01/27/1946441.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java反转字符串和相关字符编码问题 的相关文章

随机推荐

  • Matrikon OPC 模拟器使用教程

    一 OPC协议 OPC通信技术因其帮助大量的使用不同通信协议的下层现场设备的数据得以与上位机的应用程序进行交互的作用 成为了一种工业通信领域中一套广为流行的方案 它使得硬件供应商和软件开发商都可以专注于做自己的工作 只要双方都能提供OPC接
  • Python NLTK 自然语言处理入门与例程

    Python NLTK 自然语言处理入门与例程 在这篇文章中 我们将基于 Python 讨论自然语言处理 NLP 本教程将会使用 Python NLTK 库 NLTK 是一个当下流行的 用于自然语言处理的 Python 库 那么 NLP 到
  • jupyter notebook参数化运行python

    Updates 2019 8 14 19 53 吃饭前用这个方法实战了一下 吃完回来一看好像不太行 跑完一组参数之后 到跑下一组参数时好像没有释放之占用的 GPU 于是 notebook 上的结果 后面好几条都报错说 cuda out of
  • Linux系统Squid代理添加用户、密码认证

    安装了Squid后会有一些不明的流量和CPU占用95 以上 估计是因为没加密码 被扫描到端口后被滥用 我们给Squid代理添加用户 密码认证 1 密码用apache2自带的NCSA 先做个密码档 然后设为任何人可读 sudo touch e
  • make all、make clean、make install 等命令的来源

    在命令行输入make命令后 会查找当前目录下的Makefile文件来执行 一切都是自动运行的 有时候Makefile中有多个程序需要编译 这时可以使用 make all 来编译所有的程序 当然也可以使用 make 程序名 来单独编译某一个文
  • C - Coprime 2(质因数)

    C Coprime 2https vjudge csgrandeur cn problem AtCoder abc215 d1 先把a数组元素里面每个元素的因数求出来 再把他们的倍数标记 剩下的1到M没标记的数就是答案 include
  • 一般试卷的纸张大小是多少_【教学研究】标准化试卷是如何编制出来的?

    作为教师 日常教学工作中经常需要编制试卷 一般我们可以用Word来编制各类试卷 对于标准化试卷来说 有很多样式是统一的 在Word中 本文以Word2003为例 我们可以按以下步骤进行设置 一 试卷页面设置 标准化试卷一般都采用8K纸张 横
  • octave下实现积分/求解微分方程

    我电脑是AMD的不是Intel的 所以matlab很多功能用不了 矩阵乘法都用不了 虚拟机也没工夫折腾 找了octave来替代 首先安装 symbolic包 要求已安装好Python3的SymPy库 pkg install forge sy
  • MongoDB4.x创建数据库帐号,启用密码认证,启用外部ip访问,创建数据库,创建集合.

    创建数据库 use company 这样就创建了一个名称为company的数据库 但如果不创建集合 表 的话则不保存 创建集合 db createCollection employ salary 创建了一个employ salary表 创建
  • WPF的MVVM框架Stylet开发文档 14.6 StyletIoC 模块

    14 6 StyletIoC 模块 任何具有合理复杂性的应用程序都将包含大量 IoC 容器配置 有大量接口与实现的显式绑定 指定单例和其他 完全必要的 配置 默认方法是将所有这些配置放在您的引导加载程序中 这是有道理的 所有配置都在一个地方
  • ModuleNotFoundError: No module named ‘tensorflow.contrib‘ 关于TensorFlow2中没有contrib包的解决办法

    在学习中文实体识别的过程中 参考很多以前的ltsm crf代码 以及谷歌的开源bert代码 过程中都遇到了该问题 简单查阅可得这是因为TensorFlow2版本中删除了contrib包所导致的问题 其中有部分大佬给出的解决办法是降低版本 但
  • PHP 短信验证码验证(短信宝)

    注册的短信验证 控制器 public function save Request request echo 11 die phone input last time Cache store redis gt get register tim
  • nvdiffrec在Windows上的配置及使用

    nvdiffrec是NVIDIA研究院开源的项目 源代码地址 https github com NVlabs nvdiffrec 论文为 Extracting Triangular 3D Models Materials and Light
  • c++ 赋值运算符函数

    题目 如下为类型CMyString 的声明 请为该类型添加赋值运算符 class CMyString public CMyString char pData nullptr CMyString const CMyString str CMy
  • ubuntu上安装android studio出现adb 无法识别设备的问题

    ubuntu上安装android studio出现adb 无法识别某些设备的问题 出现的都是 m OptiPlex 7040 etc udev rules d adb devices List of devices attached no
  • 在Windows域控制器里新建用户,添加可以远程桌面访问的权限

    在Windows域控制器里新建用户 添加可以远程桌面访问的权限 系统Windows server2003 开始 管理工具 active directory用户和计算机 新建用户 登录到要远程的计算机 DOS窗口输入gpedit进去到本地组策
  • 使用 Filebeat 监听日志文件

    Filebeat是一个日志文件托运工具 在你的服务器上安装客户端后 filebeat 会监控日志目录或者指定的日志文件 追踪读取这些文件 追踪文件的变化 不停的读 并且转发这些信息到elasticsearch 或者 logstarsh re
  • VS2015 + CUDA10 编译 OpenCV2.4.13 之 OpenCV编译文件修改

    因为CUDA10貌似不支持OpenCV2 所以需要对OpenCV2的文件进行修改 主要参考https blog csdn net u014613745 article details 78310916 请注意 本篇博客需要结合上面的链接中的
  • 支持KEIL5! KeilFDfix_新0xFD汉字补丁(冠铭同学版)

    发布支持KEIL5 KeilFDfix 新0xFD汉字补丁 冠铭同学版 说明 将本软件放至KEIL的编译器 C51 EXE及A51 EXE 所在文件夹 例如 C KEIL V5 C51 BIN 按 开始 即可自动打补丁 将0x 80 FB
  • Java反转字符串和相关字符编码问题

    反转字符串一直被当作是简单问题 大家的思想主要就是利用遍历 首尾交换字符实现字符串的反转 例如下面的代码 就可以简单实现反转 1 public String reverse char value 2 for int i value leng