jjn*_*guy 328
我使用for循环来迭代字符串并charAt()
用来让每个字符检查它.由于String是使用数组实现的,因此该charAt()
方法是一个常量时间操作.
String s = "...stuff...";
for (int i = 0; i < s.length(); i++){
char c = s.charAt(i);
//Process char
}
Run Code Online (Sandbox Code Playgroud)
这就是我要做的.这对我来说似乎最简单.
就正确性而言,我不相信存在于此.这完全取决于您的个人风格.
Dav*_*ney 195
两种选择
for(int i = 0, n = s.length() ; i < n ; i++) {
char c = s.charAt(i);
}
Run Code Online (Sandbox Code Playgroud)
要么
for(char c : s.toCharArray()) {
// process c
}
Run Code Online (Sandbox Code Playgroud)
第一个可能更快,然后第二个可能更可读.
sk.*_*sk. 88
注意,如果您处理BMP(Unicode 基本多语言平面)之外的字符,即超出u0000-uFFFF范围的代码点,则此处描述的大多数其他技术都会被破坏.这种情况很少发生,因为此外的代码点主要分配给死语言.但是除此之外还有一些有用的字符,例如用于数学符号的一些代码点,还有一些用于用中文编码专有名称.
在这种情况下,您的代码将是:
String str = "....";
int offset = 0, strLen = str.length();
while (offset < strLen) {
int curChar = str.codePointAt(offset);
offset += Character.charCount(curChar);
// do something with curChar
}
Run Code Online (Sandbox Code Playgroud)
该Character.charCount(int)
方法需要Java 5+.
资料来源:http://mindprod.com/jgloss/codepoint.html
小智 24
我同意StringTokenizer在这里有点过分.实际上我尝试了上面的建议,并花时间.
我的测试非常简单:创建一个大约有一百万个字符的StringBuilder,将它转换为一个String,然后使用charIt()/在转换为char数组/使用CharacterIterator一千次后遍历每个字符串(当然要确保在字符串上执行某些操作,以便编译器无法优化整个循环:-)).
我的2.6 GHz Powerbook(这是一个mac :-))和JDK 1.5的结果:
由于结果显着不同,最直接的方式似乎也是最快的方式.有趣的是,StringBuilder的charAt()似乎比String更慢.
BTW我建议不要使用CharacterIterator,因为我认为它滥用'\ uFFFF'字符作为"迭代结束"是一个非常糟糕的黑客.在大项目中,总有两个人使用相同类型的黑客用于两个不同的目的,代码崩溃真的很神秘.
这是其中一项测试:
int count = 1000;
...
System.out.println("Test 1: charAt + String");
long t = System.currentTimeMillis();
int sum=0;
for (int i=0; i<count; i++) {
int len = str.length();
for (int j=0; j<len; j++) {
if (str.charAt(j) == 'b')
sum = sum + 1;
}
}
t = System.currentTimeMillis()-t;
System.out.println("result: "+ sum + " after " + t + "msec");
Run Code Online (Sandbox Code Playgroud)
Bru*_*ine 20
有一些专门的类:
import java.text.*;
final CharacterIterator it = new StringCharacterIterator(s);
for(char c = it.first(); c != CharacterIterator.DONE; c = it.next()) {
// process c
...
}
Run Code Online (Sandbox Code Playgroud)
Tou*_*uko 18
如果你的类路径上有Guava,以下是一个非常可读的替代方案.对于这种情况,Guava甚至有一个相当明智的自定义List实现,所以这不应该是低效的.
for(char c : Lists.charactersOf(yourString)) {
// Do whatever you want
}
Run Code Online (Sandbox Code Playgroud)
更新:正如@Alex指出的那样,使用Java 8也CharSequence#chars
可以使用.甚至类型是IntStream,因此它可以映射到如下的字符:
yourString.chars()
.mapToObj(c -> Character.valueOf((char) c))
.forEach(c -> System.out.println(c)); // Or whatever you want
Run Code Online (Sandbox Code Playgroud)
i_a*_*ero 16
在Java 8中,我们可以解决它:
String str = "xyz";
str.chars().forEachOrdered(i -> System.out.print((char)i));
str.codePoints().forEachOrdered(i -> System.out.print((char)i));
Run Code Online (Sandbox Code Playgroud)
方法chars()返回doc中IntStream
提到的:
返回int的流,从此序列中对char值进行零扩展.任何映射到代理代码点的char都会被解释.如果在读取流时序列被突变,则结果是未定义的.
该方法codePoints()
还IntStream
根据doc 返回:
返回此序列中的代码点值流.序列中遇到的任何代理对都被组合,就好像通过Character.toCodePoint一样,结果传递给流.任何其他代码单元(包括普通BMP字符,未配对代理和未定义代码单元)都将零扩展为int值,然后传递给流.
char和代码如何区别?正如提到的这个文章:
Unicode 3.1添加了补充字符,使总字符数超过216个字符,可以通过单个16位进行区分
char
.因此,char
值不再与Unicode中的基本语义单元进行一对一映射.更新了JDK 5以支持更大的字符值集.char
一些新的补充字符不是改变类型的定义,而是由两个char
值的代理对表示.为了减少命名混淆,将使用代码点来指代表示特定Unicode字符的数字,包括补充字符.
最后为什么forEachOrdered
不forEach
呢?
如果流具有已定义的遭遇顺序,则在流的遭遇顺序中执行针对此流的每个元素的操作时,行为forEach
明确是非确定性的.所以不保证订单会被保留.另请查看此问题.forEachOrdered
forEach
对于字符,代码点,字形和字形之间的差异,请检查此问题.
Ale*_*lex 13
如果你需要遍历a的代码点String
(参见这个答案),更简单/更易读的方法是使用CharSequence#codePoints
Java 8中添加的方法:
for(int c : string.codePoints().toArray()){
...
}
Run Code Online (Sandbox Code Playgroud)
或直接使用流而不是for循环:
string.codePoints().forEach(c -> ...);
Run Code Online (Sandbox Code Playgroud)
还有CharSequence#chars
,如果你想要的字符流(虽然它是IntStream
,因为没有CharStream
).
归档时间: |
|
查看次数: |
416842 次 |
最近记录: |