Foreach无法操纵String列表?

时间:2016-03-18 05:59:13

标签: java list immutability pass-by-value

我在主题上找到了this主题,我想知道为什么用Java替换List中的值这么难。

我的代码看起来像这样丑陋:

    List<String> stringList = new ArrayList<>();
    // ... add some elements
    for (int i = 0; i< stringList.size(); ++i) {
        if (stringList.get(i).contains("%")) {
            stringList.set(i, stringList.get(i).replace("%", backupStorePath));
        }
    }

这真的是唯一的方法吗?为什么我不能使用foreach循环?

for (String command : stringList) {
    command = command.replace("%", backupStorePath);
}

这必须是java的“按值复制”问题并且String是不可变的,但为什么它是这样实现的呢?为什么command是原始引用的副本而不是原始引用?

3 个答案:

答案 0 :(得分:5)

从Java-8开始,您有了一个使用List.replaceAll的新选项:

stringList.replaceAll(command -> command.replace("%", backupStorePath));

请注意,for循环适用于任何Iterable,而不仅仅适用于List。并且大多数其他迭代不支持元素替换。因此,即使Java设计者决定支持修改,也有必要将List和非List案例分开,这肯定会增加一些复杂性。

答案 1 :(得分:3)

来自Java Programming Language: The For-Each Loop 强调 已添加)

  

for-each循环隐藏了迭代器,因此您无法调用remove。因此,for-each循环不可用于过滤。 同样,它不适用于需要在遍历时替换列表或数组中的元素的循环。 最后,它不适用于必须遍历多个循环的循环收集并行。这些缺点是设计师所熟知的,他们有意识地决定采用干净,简单的结构来覆盖绝大多数情况。

您可以使用Iteratorindex。像

这样的东西
// ... add some elements
Iterator<String> stringIter = stringList.iterator();
int i = 0;
while (stringIter.hasNext()) {
    String command = stringIter.next();
    if (command.contains("%")) {
        command = command.replace("%", backupStorePath);
        stringList.set(i, command);
    }
    i++;
}

答案 2 :(得分:0)

它会是这样的:

List list1 = new ArrayList();
List list 2 = list1;
list2 = new LinkedList();  //this just make list2 to point to an new Object no reference about list1.

所以你的代码:

command = command.replace("%", backupStorePath);  //this just make command to a new point of memory not have any chang about your list