迭代时在Java8中修改流内的对象

时间:2015-06-11 10:17:21

标签: java java-8 java-stream

在Java8流中,我是否可以修改/更新其中的对象? 例如。 users.stream().forEach(u -> u.setProperty("value"))

onCreate()

9 个答案:

答案 0 :(得分:67)

是的,您可以修改流中的对象状态,但应避免修改流的 的状态。从流包文档的non-interference部分我们可以读到:

  

对于大多数数据源,防止干扰意味着在执行流管道期间确保数据源不会在所有上进行修改。值得注意的例外是其源是并发集合的流,这些集合专门用于处理并发修改。并发流源是Spliterator报告CONCURRENT特征的那些。

所以这没关系

List<User> users = getUsers();
users.stream().forEach(u -> u.setProperty(value));

但是

users.stream().forEach(u -> users.remove(u));

不是,可能会抛出ConcurrentModificationException或其他例外,如NPE:

List<Integer> list = IntStream.range(0, 10).boxed().collect(Collectors.toList());

list.stream()
    .filter(i -> i > 5)
    .forEach(i -> list.remove(i));  //throws NullPointerException

答案 1 :(得分:3)

要对流的源进行结构修改,正如Pshemo在他的回答中提到的,一个解决方案是使用主列表中的项创建this.getMyData = function() { //`return` & `$http` promise should be on same line, otherwise undefined would get return return $http({ method: 'GET', url: 'myList.json', headers: { 'Content-Type': 'application/json' } }).then(function successCallback(response) { console.log(response); return response; }, function errorCallback(response) { console.log(error); return response; }); }; 的新实例,如Collection;迭代新列表,并在主列表上执行操作。

ArrayList

答案 2 :(得分:2)

功能方式将是:

import static java.util.stream.Collectors.toList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

public class PredicateTestRun {

    public static void main(String[] args) {

        List<String> lines = Arrays.asList("a", "b", "c");
        System.out.println(lines); // [a, b, c]
        Predicate<? super String> predicate = value -> "b".equals(value);
        lines = lines.stream().filter(predicate.negate()).collect(toList());

        System.out.println(lines); // [a, c]
    }
}

在此解决方案中,原始列表未被修改,但应在新列表中包含您的预期结果,该列表可在与旧旧列表相同的变量下访问

答案 3 :(得分:1)

是的,您也可以根据情况修改或更新列表中对象的值:

users.stream().forEach(u -> u.setProperty("some_value"))

但是,以上语句将对源对象进行更新。在大多数情况下可能不可接受。

幸运的是,我们还有另一种方式:

List<Users> updatedUsers = users.stream().map(u -> u.setProperty("some_value")).collect(Collectors.toList());

在不妨碍旧列表的情况下,这将返回更新列表。

答案 4 :(得分:0)

摆脱 ConcurrentModificationException 使用 CopyOnWriteArrayList

答案 5 :(得分:0)

您可以先filter()然后再map()您的结果,而不是制造奇怪的东西。

这更具可读性和确定性。流将仅使它循环一遍。

答案 6 :(得分:0)

如前所述-您无法修改原始列表,但可以流式传输,修改并将项目收集到新列表中。这是如何修改字符串元素的简单示例。

public class StreamTest {

    @Test
    public void replaceInsideStream()  {
        List<String> list = Arrays.asList("test1", "test2_attr", "test3");
        List<String> output = list.stream().map(value -> value.replace("_attr", "")).collect(Collectors.toList());
        System.out.println("Output: " + output); // Output: [test1, test2, test3]
    }
}

答案 7 :(得分:0)

您可以利用removeIf有条件地从列表中删除数据。

例如:-如果要从列表中删除所有偶数,则可以按以下步骤进行操作。

    final List<Integer> list = IntStream.range(1,100).boxed().collect(Collectors.toList());

    list.removeIf(number -> number % 2 == 0);

答案 8 :(得分:-1)

这可能有点晚了。但这是用法之一。这可以获取文件数量的计数。

创建一个指向内存的指针(在这种情况下为新obj),并修改对象的属性。 Java 8流不允许修改指针本身,因此,如果您声明只将count视为变量并尝试在流中进行递增操作,它将永远无法工作,并且首先会引发编译器异常

scrollArea = QtGui.QScrollArea(self)
scrollArea.setWidgetResizable(False)
scrollArea.setGeometry(210, 150, 800, 450)
highlightLbl = QtGui.QLabel(self)
highlight_dir = url + '\\highlighted'
scrollArea = QtGui.QScrollArea(self)
scrollArea.setWidgetResizable(False)
scrollArea.setGeometry(210, 150, 800, 450)
for file in os.listdir(highlight_dir):
    highlighted_img = QtGui.QPixmap(os.path.join(highlight_dir, file))
    highlightLbl.setPixmap(highlighted_img)
    scrollArea.setWidget(highlightLbl)