java 遍历String
Java字符串是一系列的Unicode字符序列,但是,它却常常被误认为是char序列。于是,我们经常这样来遍历字符串:
package testchar;
public class TestChar2 {
	public static void main(String[] args) {
		String s = "\u0041\u00DF\u6771\ud801\uDC00";
		for(int i = 0; i < s.length(); i++) {
			System.out.println(s.charAt(i));
		}
	}
}
然后,得到了意料之外的结果:
A
ß
東
?
?
之所以会这样,是因为Unicode字符和Java的char类型不能等同起来。实际上,Java中的char类型能表示的字符只是Unicode字符的子集,因为char只有16位,也就是说,它只能表示65536(2的16次方)个字符,但实际的Unicode字符数超过这个数字。在Java中,用UTF-16编码char和String中的字符,一个字符对应的编码值被称为一个代码点。有的代码点用16位编码,被称为一个代码单元,像char表示的那些字符;有的代码点用32位编码,也就是用两个连续的代码单元编码,如上文中的\ud801\uDC00。其实,我们遍历一个字符串,遍历的是这个字符串中所有代码点,而
s.length()
返回的是字符串s中代码单元的个数。当i对应的代码单元只是一个32位代码点的一部分时,
s.charAt(i)
也就不能像我们希望的那样工作了。
下面给出了几种正确遍历一个字符串的方法:
package testchar; /**
* 正确遍历String
*
* @author yuncong
*
*/
public class TestChar { public static void main(String[] args) {
String s = "\u0041\u00DF\u6771\ud801\uDC00";
// 获得字符串中代码点的数量
int cpCount = s.codePointCount(0, s.length());
for (int i = 0; i < cpCount; i++) {
int index = s.offsetByCodePoints(0, i);
int cp = s.codePointAt(index);
if (!Character.isSupplementaryCodePoint(cp)) {
System.out.println((char) cp);
} else {
System.out.println(cp);
}
} System.out.println("-------------------"); for (int i = 0; i < s.length(); i++) {
int cp = s.codePointAt(i);
if (!Character.isSupplementaryCodePoint(cp)) {
System.out.println((char) cp);
} else {
System.out.println(cp);
i++;
}
} System.out.println("-------------------"); // 逆向遍历字符串
for(int i = s.length() - 1; i >= 0; i--) {
int cp = 0;
// 当i等于0的时候,只剩下一个代码单元,不可能是辅助字符
if (i == 0) {
cp = s.codePointAt(0);
System.out.println((char)cp);
} else {
// 只有在i大于0的时候才可以退,并且
// 因为剩下的代码单元大于2,所以接下
// 来访问的两个代码单元可能表示辅助
// 字符;
// 退一个代码单元
i--;
cp = s.codePointAt(i);
if (Character.isSupplementaryCodePoint(cp)) {
System.out.println(cp);
} else {
// 如果cp不是辅助字符,就回到遍历的正常位置
i++;
cp = s.codePointAt(i);
System.out.println((char)cp);
}
}
} } }
(天坑啊,博客中不能出现Java中的辅助字符)
java 遍历String的更多相关文章
- java 遍历map 方法 集合 五种的方法
		
package com.jackey.topic; import java.util.ArrayList;import java.util.HashMap;import java.util.Itera ...
 - java中String类型变量的赋值问题
		
第一节 String类型的方法参数 运行下面这段代码,其结果是什么? package com.test; public class Example { String str = new String( ...
 - java 遍历文件夹里的文件
		
Java遍历文件夹的2种方法: A.不使用递归: import java.io.File; import java.util.LinkedList; public class FileSystem { ...
 - JAVA 遍历文件夹下的所有文件
		
JAVA 遍历文件夹下的所有文件(递归调用和非递归调用) 1.不使用递归的方法调用. public void traverseFolder1(String path) { int fileNum = ...
 - java遍历树(深度遍历和广度遍历
		
java遍历树如现有以下一颗树:A B B1 B11 B2 B22 C C ...
 - 解决spring mvc 上传报错,Field [] isn't an enum value,Failed to convert value of type 'java.lang.String[]' to required type '
		
没有选择附件,但是点击上传按钮的时候会报错. 之前不选择文件,直接上传空文件是可以的,后来不知道改了什么就不行了. 错误信息: -- :: [http--] TRACE org.springframe ...
 - java遍历Hashmap/Hashtable的几种方法
		
一>java遍历Hashtabe: import java.util.Hashtable; import java.util.Set; public class HashTableTest { ...
 - JAVA 遍历文件夹下的所有文件(递归调用和非递归调用)
		
JAVA 遍历文件夹下的所有文件(递归调用和非递归调用) 1.不使用递归的方法调用. public void traverseFolder1(String path) { int fileNum = ...
 - java 遍历List 和 Map的几种方法
		
java遍历List 1.(性能最差) for(String tmp:list) { //System.out.println(tmp); } 2.(性能最好) for(int i = 0; i &l ...
 
随机推荐
- JMeter 八:录制脚本--使用Jmeter自带的代理服务器
			
参考:http://jmeter.apache.org/usermanual/jmeter_proxy_step_by_step.pdf http://jmeter.apache.org/userma ...
 - Unity3D研究院之DontDestroyOnLoad的坑
			
http://www.xuanyusong.com/archives/2938 Unity中的一个方法DontDestroyOnLoad可以让某些游戏对象在切换场景的时候不是施放,听起来是一个非常好的 ...
 - 算法笔记_105:蓝桥杯练习 算法提高 上帝造题五分钟(Java)
			
目录 1 问题描述 2 解决方案 1 问题描述 问题描述 第一分钟,上帝说:要有题.于是就有了L,Y,M,C 第二分钟,LYC说:要有向量.于是就有了长度为n写满随机整数的向量 第三分钟,YUHC ...
 - raspberry pi install iceweasel
			
sudo apt-get update sudo apt-get upgrade sudo apt-get install iceweasel
 - Android源码-SignApk.java
			
/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Versi ...
 - Getting started with Chrome Dev Editor
			
转自:https://github.com/GoogleChrome/chromedeveditor/blob/master/doc/GettingStarted.md Installation In ...
 - 常见SQL Server导入导出数据的几个工具
			
摘自:http://www.cnblogs.com/chenxizhang/archive/2011/06/09/2076542.html 在我们的日常工作中,与数据库打交道的机会越来越多.这一篇文章 ...
 - 用GDB命令PO(print-object)打印UIView的视图层级
			
UIView有一个私有方法: recursiveDescription 这个方法可以显示出当前视图的详细层级,可以在代码中直接调用,也可以在GDB中调用,在GDB中调用时需要借助另一个GDB命令:pr ...
 - 堆越界--coredump 在malloc函数里
			
一,可执行程序分析: objdump -h xxx,可以看到程序内部各个段的内存分布,结果如下(部分): 26 .data 0000016c 0000000000879d20 0 ...
 - mysql 常用功能
			
一.备份 mysqldump [OPTIONS] database [tables] http://www.blogjava.net/Alpha/archive/2007/08/10/135694.h ...