在Java中检测for-each循环的第一次迭代

30

我正在处理一个向客户端返回字符分隔列表的服务器。 为了构建这些列表,我必须检测for-each循环的第一次迭代:

    StringBuilder builder = new StringBuilder() ;
    boolean firstIterationFlag = true ;

    for ( String s : list ){
        if ( firstIterationFlag) {
            firstIterationFlag = false ;
        } else {
            builder.append(separator);
        }
        builder.append(s) ;         
   }
   return builder.toString() ;

有没有一种不使用标志的方法来实现这个?


为什么你需要检测循环的第一次迭代? - BeRecursive
你可以手动使用普通的 for 循环,从索引 1 开始而不是从 0 开始,来代替 forEach 循环。 - Sheriff
2
看看这个SO问题:https://dev59.com/rXVD5IYBdhLWcg3wKoWH - 它可能是比你的更好的解决方案。 - Aleks G
...或者使用list.indexOf(s)来获取索引... - viliam
1
@vilo:这可能会对每次迭代造成线性时间的影响,因此在将一些文本粘合在一起的例程中会产生O(n^2)的影响。 - andersoj
@andersoj:你说得对。我没有考虑到那一点。我以为这是关于代码优化(小字符串集合)的问题。org.apache.commons.StringUtils.join()看起来不错。 - viliam
9个回答

21

在这种情况下,更简单的方法是注意到您可以始终附加一个空字符串:

// For the first iteration, use a no-op separator
String currentSeparator = "";
for (String s : list) {
    builder.append(currentSeparator);
    builder.append(s);
    // From the second iteration onwards, use this
    currentSeparator = separator;
}

或者(而且更好的选择)使用Guava的Joiner类来开始处理:

“连接器”场景几乎总是要求的场景 - 因此只需使用Joiner。对于其他场景,可以使用常规的for循环或按照您的代码使用条件。


1
消除了“if”,但更难理解。 - Israel Unterman
我使用Apache commons-lang中的StringUtils.join。 - Ravi Wallau
在我了解Guava的Joiner之前,我也是这样的,@raviWallau。 - Sean Patrick Floyd

9

不使用foreach,而是手动使用迭代器:

Iterator<String> it = list.iterator();
if(it.hasNext()){
    doSomeThingForTheFirstTime(it.next());
    while(it.hasNext()){
        doSomethingElse(it.next);
    }
}

(顺便说一句,这基本上就是Guava的Joiner类在更高层次上所执行的操作。)

3

Java 8 解决方案

如果您使用的是 Java 8,您可以直接使用String#join方法,无需使用 Guava:

String.join(", ", list)

3
在你提到的具体情况中,使用Guava的Joiner而不是自己编写...

一个将文本片段(作为数组、Iterable、varargs甚至Map指定)用分隔符连接起来的对象。它可以将结果附加到Appendable中,也可以将它们作为字符串返回。例如:

Joiner joiner = Joiner.on(separator).skipNulls();
return joiner.join(list);

1
+1(Guava的Joiner比Apache Commons中的任何东西都要好得多) - Sean Patrick Floyd

1
你可以尝试这个:)

int i = 0;
for (something : manythings) {
    i++;
}

1

仅仅是为了好玩,这里提供另一种选择。

    StringBuilder builder = new StringBuilder();
    for (String s : list) {
        builder.append(separator);
        builder.append(s);
    }
    builder.deleteCharAt(0);
    return builder.toString();

0

0

你也可以使用以下方法:

public static String toString(List<?> list, String separator) {
    StringBuilder sb = new StringBuilder();
    Iterator<?> it = list.iterator();
    while (it.hasNext()) {
        Object next = it.next();
        sb.append(next);
        if (it.hasNext()) {
            sb.append(separator);
        }
    }
    return sb.toString();
}

增强型的 for 语句相当于基本形式的 for 语句:

for (I #i = Expression.iterator(); #i.hasNext(); ) {
    VariableModifiersopt TargetType Identifier =
        (TargetType) #i.next();
    Statement
}

#i 是一个自动生成的标识符。


0

好的,这不会检测循环中的第一次迭代,但可以解决问题。只需在每个字符串的末尾添加分隔符并去掉最后一个分隔符即可。

StringBuilder builder = new StringBuilder() ;

for ( String s : list ) {
    builder.append(s) ;         
    builder.append(separator);
}
builder.setLength(builder.length() - separator.length());
return builder.toString() ;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接