programing

Collection.stream().forEach()와 Collection.forEach()의 차이점은 무엇입니까?

goodsources 2022. 8. 27. 10:26
반응형

Collection.stream().forEach()와 Collection.forEach()의 차이점은 무엇입니까?

는 그것을 한다..stream() 이렇게 연쇄 을 할 수 .filter()병렬 스트림을 사용합니다.그러나 작은 작업(리스트 요소 인쇄 등)을 수행해야 하는 경우에는 어떤 차이가 있습니까?

collection.stream().forEach(System.out::println);
collection.forEach(System.out::println);

그림과 같이 간단한 경우는 거의 동일합니다.그러나 중요한 몇 가지 미묘한 차이가 있습니다.

한 가지 문제는 주문에 관한 것입니다.★★★★★★★★★★★★★★★★ Stream.forEach순서는 정의되어 있지 않습니다.시퀀셜 스트림에서는 발생하지 않을 가능성이 높지만 다음 사양에 준거하고 있습니다.Stream.forEach을 사용법이 문제는 병렬 스트림에서 자주 발생합니다. by by by by byIterable.forEach됩니다.Iterable(일부러)

을 하다에서 Stream.forEach간섭하지 않아야 합니다.(java.util.stream 패키지 문서를 참조하십시오). Iterable.forEach제한사항이 적을 수 있습니다.「 」의 는,java.util,Iterable.forEach으로는 그 that that that that that that that that that that that that that 를 사용합니다.Iterator이 중 대부분은 Fail Fast를 지원하도록 설계되어 있습니다.ConcurrentModificationException반복 중에 컬렉션이 구조적으로 변경된 경우.그러나 반복 중에는 구조적이지 않은 수정이 허용됩니다.를 들어 ArrayList 클래스 문서에는 "요소의 값만 설정하는 것은 구조 수정이 아닙니다."라고 나와 있습니다.그 때문에, 의 액션은ArrayList.forEach 값 됩니다.ArrayList문제없이.

동시 컬렉션이 다시 다릅니다.Fail-Fast 대신 일관성이 약하도록 설계되어 있습니다.완전한 정의는 그 링크에 있습니다.단, 간단히 생각해 봅시다.ConcurrentLinkedDeque은 .션 to to its its its its its its its its forEach메서드는 구조적으로도 기본 디큐를 변경할 수 있습니다.ConcurrentModificationException절대 던지지 않습니다.의 일관성을.)(어느 쪽인가 하면)

다른 , 라고 하면 또 다른 차이점이 보인다.Iterable.forEach동기화된 수집을 반복하고 있습니다.에서는, 「 」의Iterable.forEach 는 컬렉션의 잠금을 1회 취득하여 액션메서드에 대한 모든 콜에서 잠금을 유지합니다.Stream.forEach콜은 콜의 스플리터를 사용합니다.이 스플리터는 잠기지 않고 일반적인 비간섭 규칙에 의존합니다.반복 할 수 스트림을 지원하는 컬렉션을 할 수 .★★★★★★★★★★★★★★★★,ConcurrentModificationException또는 일관성이 없는 동작이 발생할 수 있습니다.

이 답변은 루프의 다양한 실장의 퍼포먼스와 관련이 있습니다.이것은 매우 자주(수백만 개의 콜과 같이)라고 불리는 루프에 약간만 관련이 있습니다.대부분의 경우 루프의 내용은 단연코 가장 비용이 많이 드는 요소가 됩니다.루프 빈도가 매우 높은 상황에서도, 이것은 여전히 도움이 될 수 있습니다.

이 테스트는 구현에 따라 다르므로 대상 시스템에서 반복해야 합니다(전체 소스 코드).

고속 Linux 시스템에서 openjdk 버전 1.8.0_111을 실행하고 있습니다.

^6은 다양한 크기의 코드를 사용하여 목록 했습니다.integers(10^0 -> 10^5 엔 ( 。

결과는 다음과 같습니다.가장 빠른 방법은 목록의 항목 수에 따라 달라집니다.

그러나 여전히 최악의 상황에서는 10^5 엔트리를 10^6회 이상 반복하는 데 100초가 걸리기 때문에 거의 모든 상황에서 다른 고려사항이 더 중요합니다.

public int outside = 0;

private void iteratorForEach(List<Integer> integers) {
    integers.forEach((ii) -> {
        outside = ii*ii;
    });
}

private void forEach(List<Integer> integers) {
    for(Integer next : integers) {
        outside = next * next;
    }
}

private void forCounter(List<Integer> integers) {
    for(int ii = 0; ii < integers.size(); ii++) {
        Integer next = integers.get(ii);
        outside = next*next;
    }
}

private void iteratorStream(List<Integer> integers) {
    integers.stream().forEach((ii) -> {
        outside = ii*ii;
    });
}

타이밍은 다음과 같습니다.밀리초 / 함수 / 목록 내 엔트리 수각 실행은 10^6 루프입니다.

                           1    10    100    1000    10000
       iterator.forEach   27   116    959    8832    88958
               for:each   53   171   1262   11164   111005
         for with index   39   112    920    8577    89212
iterable.stream.forEach  255   324   1030    8519    88419

실험을 반복하면 소스코드 전체를 올렸습니다.이 답변을 편집하고 테스트한 시스템의 표기를 사용하여 결과를 추가하십시오.


MacBook Pro, 2.5GHz 인텔 Core i7, 16GB, MacOS 10.12 사용.6:

                           1    10    100    1000    10000
       iterator.forEach   27   106   1047    8516    88044
               for:each   46   143   1182   10548   101925
         for with index   49   145    887    7614    81130
iterable.stream.forEach  393   397   1108    8908    88361

Java 8 핫스팟 VM - 3.4GHz 인텔 Xeon, 8 GB, Windows 10 Pro

                            1    10    100    1000    10000
        iterator.forEach   30   115    928    8384    85911
                for:each   40   125   1166   10804   108006
          for with index   30   120    956    8247    81116
 iterable.stream.forEach  260   237   1020    8401    84883

VM - 4Java 11 - 3.4 인텔 10 © Xeon, 8GB, Windows 10 Pro
, JDK (JDK)

                            1    10    100    1000    10000
        iterator.forEach   20   104    940    8350    88918
                for:each   50   140    991    8497    89873
          for with index   37   140    945    8646    90402
 iterable.stream.forEach  200   270   1054    8558    87449

Java 11 OpenJ9 VM - 3.4GHz 인텔 Xeon, 8 GB, Windows 10 Pro
및 , VMVM의 경우 JDK의 경우,

                            1    10    100    1000    10000
        iterator.forEach  211   475   3499   33631   336108
                for:each  200   375   2793   27249   272590
          for with index  384   467   2718   26036   261408
 iterable.stream.forEach  515   714   3096   26320   262786

Java 8 핫스팟 VM - 2.8GHz AMD, 64 GB, Windows Server 2016

                            1    10    100    1000    10000
        iterator.forEach   95   192   2076   19269   198519
                for:each  157   224   2492   25466   248494
          for with index  140   368   2084   22294   207092
 iterable.stream.forEach  946   687   2206   21697   238457

VM - 8Java 11 - 2.8 AMD, GB, Server GHz AMD, 64 GB, Windows Server 2016
, JDK (JDK)

                            1    10    100    1000    10000
        iterator.forEach   72   269   1972   23157   229445
                for:each  192   376   2114   24389   233544
          for with index  165   424   2123   20853   220356
 iterable.stream.forEach  921   660   2194   23840   204817

Java 11 OpenJ9 VM - 2.8GHz AMD, 64 GB, Windows Server 2016
및 , VMVM의 경우 JDK의 경우,

                            1    10    100    1000    10000
        iterator.forEach  592   914   7232   59062   529497
                for:each  477  1576  14706  129724  1190001
          for with index  893   838   7265   74045   842927
 iterable.stream.forEach 1359  1782  11869  104427   958584

선택하는 VM 구현에 따라 Hotspot/OpenJ9/등도 달라집니다.

두 사이에는 가 없습니다.최소한 개념적으로는Collection.forEach()그냥 줄임말일 뿐이야

으로는, 「」라고 하는 일컬어지고 있습니다.stream()버전에서는 오브젝트 작성으로 인해 오버헤드가 다소 증가하지만 실행 시간을 보면 오버헤드가 발생하지 않습니다.

구현 모두 '아,어,어,어,어,느끼다느끼다느끼다느끼다느끼다느끼다느끼다느끼다느끼다느끼다느끼다느끼다느끼다느끼다느끼다.collection내용을 한 번 인쇄하고 반복하는 동안 요소를 인쇄합니다.

Collection.forEach()는 컬렉션의 반복기(지정된 경우)를 사용합니다.즉, 항목의 처리 순서가 정해져 있습니다.반대로 Collection.stream().ForEach()의 처리순서는 정의되어 있지 않습니다.

대부분의 경우, 둘 중 어느 쪽을 선택하든 상관없습니다.병렬 스트림을 사용하면 스트림을 여러 스레드로 실행할 수 있으며 이러한 상황에서는 실행 순서가 정의되지 않습니다.Java는 Collectors.toList() 등의 터미널 조작을 호출하기 전에 모든 스레드를 완료해야 합니다.먼저 컬렉션에서 직접 Each()를 호출하고 다음으로 병렬 스트림에서 호출하는 예를 살펴보겠습니다.

list.forEach(System.out::print);
System.out.print(" ");
list.parallelStream().forEach(System.out::print);

코드를 여러 번 실행하면 list.forEach()는 삽입 순서대로 항목을 처리하는 반면 list.parallelStream()은 실행마다 다른 결과를 생성합니다.출력은 다음과 같습니다.

ABCD CDBA

또 다른 예는 다음과 같습니다.

ABCD DBCA

언급URL : https://stackoverflow.com/questions/23218874/what-is-difference-between-collection-stream-foreach-and-collection-foreach

반응형