循环遍历Java字符串字符的规范方法——类似python for ch in string
比如我将string作为CNN 文本处理输入:
float [] input = new float[maxLength]; // 1 sentence by maxLenWords // int[] input = new int[batchSize * maxLength]; // 1 sentence by maxLenWords int i = 0; final int length = subdomain.length(); for (int offset = 0; offset < length; ) { final int codepoint = subdomain.codePointAt(offset); // do something with the codepoint if(vocabMap.containsKey(codepoint)) { input[i] = vocabMap.get(codepoint); } else { Log.e(TAG, "not found char in dict, check code point:" + codepoint + " subdomain:"+subdomain + " offset:" +offset); } i += 1; offset += Character.charCount(codepoint); }
其中,vocabMap为词汇表。构建方法:
Gson gson = new GsonBuilder().setPrettyPrinting().create(); Type type = new TypeToken<Map<String, Integer>>(){}.getType(); Map<String,Integer> tmpMap = gson.fromJson(json, type); vocabMap = new HashMap<Integer, Integer>(); maxLength = tmpMap.get("__MAX_DOC_LEN__"); volcabSize = tmpMap.get("__VOLCAB_SIZE__"); for (String s: tmpMap.keySet()) { if (getPointLength(s) == 1) { vocabMap.put(s.codePointAt(0), tmpMap.get(s)); } else { Log.e(TAG, "****Check dict key:" + s + " point:" + s.codePointAt(0) + " point lenth=" + getPointLength(s)); } } Log.e(TAG, "load dict OK. maxLength:" + maxLength + " volcabSize:" + volcabSize + " DictSize:" + (vocabMap.size()));
注意每一次迭代都是int。
下面是详细解释:
循环遍历Java字符串的字符的规范方法:
final int length = s.length();
for (int offset = 0; offset < length; ) {
final int codepoint = s.codePointAt(offset);
// do something with the codepoint
offset += Character.charCount(codepoint);
}
http://stackoverflow.com/questions/1527856/how-can-i-iterate-through-the-unicode-codepoints-of-a-java-string
Java 正确遍历字符串
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); } } } } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
2017-02-26 四川南部县护照办理
2017-02-26 营山护照办理
2017-02-26 非北京人员 办理护照
2017-02-26 护照填写注意事项