将for 转换为while
您只需了解for 循环的工作原理,即可将任何for 循环转换为while 循环。这是一个简单的例子:
for (A; B; C) {
D;
}
等价于
A;
while (B) {
D;
C;
}
但是,在您的具体情况下,您使用的不是传统的 for 循环,而是增强的 for 循环。其中,对于collections(任何Iterable)等同于使用Iterator:
// elements being a collection like List<E>
for (E element : elements) {
...
}
和
一样
Iterator<E> elementIter = elements.iterator();
while (elementIter.hasNext()) {
E element = elementIter.next();
...
}
但是,在您的特定情况下,您在数组上使用了增强的 for 循环。将其转换为传统的基于索引的 for 循环。所以
// elements being an array like E[]
for (E element : elements) {
...
}
等价于
for (int i = 0; i < elements.length; i++) {
E element = elements[i];
...
}
我们可以轻松地将其转换为while 循环,如前所示:
int i = 0;
while (i < elements.length) {
E element = elements[i];
...
i++;
}
您的代码
话虽如此,现在让我们看看您的代码。在我们开始更详细地考虑您的代码之前,让我们盲目地应用上述转换:
第一步,将增强的for循环转换为传统的for循环:
String[][] wordData = {
{"study", "consider", "examine", "learn"},
{"ponder", "read", "think", "cogigate"}
};
int characterCount = 0;
for (int i = 0; i < wordData.length; i++) {
String[] stringRow = wordData[i];
for (int j = 0; j < stringRow.length; i++) {
String s = stringRow[j];
characterCount += s.length();
}
}
System.out.println(characterCount);
现在 while 循环:
String[][] wordData = {
{"study", "consider", "examine", "learn"},
{"ponder", "read", "think", "cogigate"}
};
int characterCount = 0;
int i = 0;
while (i < wordData.length) {
String[] stringRow = wordData[i];
int j = 0;
while (j < stringRow.length) {
String s = stringRow[j];
characterCount += s.length();
j++;
}
i++;
}
System.out.println(characterCount);
如您所见,这相当容易。
流
在我们讨论的同时,让我也向您展示一种如何使用流来解决您的任务的方法,因为它非常简短和优雅:
int characterCount = Stream.of(wordData) // Stream<String[]>
.flatMap(Stream::of) // Stream<String>
.mapToInt(String::length) // IntStream
.sum();
Unicode
关于 Unicode 缺陷的最后一点说明。您正在使用String::length 测量characterCount。这可能适用于您感兴趣的所有情况。但是,对于 Unicode 表中 更高 的符号,它将输出不正确的值。
例如字符串:
??
长度为4。我不是在开玩笑,"??".length() 返回 4 而不是 2。
这是因为像? 或? 这样的符号实际上需要2 个chars 来表示。 Unicode 是一种可变字节长度编码,因此并非所有符号都适合 Java char 使用的 16 位。因此,如果您希望您的代码也适用于此类符号,则必须使用 code points 而不是简单的普通 string length。
幸运的是,在 Java 中执行此操作仍然相当简单。以下是也适用于此类输入的流版本:
int characterCount = Stream.of(wordData)
.flatMap(Stream::of)
.mapToInt(s -> s.codePointCount(0, s.length())
.sum();