반복하는 동안 Java8의 스트림 내에서 객체 수정
Java8 스트림에서 객체를 수정 / 업데이트 할 수 있습니까? 예를 들어. List<User> users
:
users.stream().forEach(u -> u.setProperty("value"))
예, 스트림 내부의 객체 상태를 수정할 수 있지만 스트림 소스 의 상태는 수정하지 않아야 합니다. 에서 비 간섭 우리가 읽을 수 스트림 패키지 문서의 섹션 :
대부분의 데이터 소스에서 간섭 방지 는 스트림 파이프 라인을 실행하는 동안 데이터 소스가 전혀 수정되지 않도록하는 것을 의미합니다 . 이에 대한 주목할만한 예외는 소스가 동시 수정을 처리하도록 특별히 설계된 동시 컬렉션 인 스트림입니다. 동시 스트림 소스는 특성을
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
기능적인 방법은 다음과 같습니다.
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]
}
}
이 솔루션에서 원래 목록은 수정되지 않지만 이전 목록과 동일한 변수에서 액세스 할 수있는 새 목록에 예상 결과를 포함해야합니다.
Pshemo가 답변에서 언급했듯이 스트림 소스에 대한 구조적 수정을 수행하려면 한 가지 해결책은 기본 목록 내의 항목 으로 Collection
좋아요 의 새 인스턴스를 만드는 것 ArrayList
입니다. 새 목록을 반복하고 기본 목록에서 작업을 수행합니다.
new ArrayList<>(users).stream().forEach(u -> users.remove(u));
ConcurrentModificationException을 제거 하려면 CopyOnWriteArrayList를 사용하십시오.
대신에 이상한 물건을 만드는, 당신은 할 수있는 filter()
한 후 map()
당신의 결과.
이것은 훨씬 더 읽기 쉽고 확실합니다. 스트림은 단 하나의 루프로 만들 것입니다.
이전에 언급했듯이 원래 목록은 수정할 수 없지만 항목을 새 목록으로 스트리밍, 수정 및 수집 할 수 있습니다. 다음은 문자열 요소를 수정하는 방법에 대한 간단한 예입니다.
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]
}
}
를 사용하여 removeIf
조건부로 목록에서 데이터를 제거 할 수 있습니다 .
예 :-목록에서 모든 짝수를 제거하려면 다음과 같이 할 수 있습니다.
final List<Integer> list = IntStream.range(1,100).boxed().collect(Collectors.toList());
list.removeIf(number -> number % 2 == 0);
조금 늦을 수 있습니다. 그러나 여기에 사용법 중 하나가 있습니다. 이것은 파일 수를 가져옵니다.
메모리에 대한 포인터 (이 경우 새 obj)를 만들고 개체의 속성을 수정합니다. Java 8 스트림은 포인터 자체를 수정할 수 없으므로 변수로 카운트 만 선언하고 스트림 내에서 증가하려고하면 작동하지 않으며 처음에 컴파일러 예외가 발생합니다.
Path path = Paths.get("/Users/XXXX/static/test.txt");
Count c = new Count();
c.setCount(0);
Files.lines(path).forEach(item -> {
c.setCount(c.getCount()+1);
System.out.println(item);});
System.out.println("line count,"+c);
public static class Count{
private int count;
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
@Override
public String toString() {
return "Count [count=" + count + "]";
}
}
'Nice programing' 카테고리의 다른 글
Python의 '열거'함수에 해당하는 Java가 있습니까? (0) | 2020.11.18 |
---|---|
: before와 :: before의 차이점은 무엇입니까? (0) | 2020.11.18 |
android-sdk 및 sdk 폴더를 다른 드라이브로 이동 (0) | 2020.11.18 |
reStructuredText에서 링크의 텍스트 서식 지정 (0) | 2020.11.18 |
c ++, std :: atomic, std :: memory_order는 무엇이며 어떻게 사용합니까? (0) | 2020.11.18 |