Iterator versus Stream of Java 8

后端 未结 2 1433
日久生厌
日久生厌 2020-12-04 08:48

To take advantage of the wide range of query methods included in java.util.stream of Jdk 8 I am attempted to design domain models where getters of relationship

2条回答
  •  眼角桃花
    2020-12-04 09:36

    Let’s compare the common operation of iterating over all elements, assuming that the source is an ArrayList. Then, there are three standard ways to achieve this:

    • Collection.forEach

      final E[] elementData = (E[]) this.elementData;
      final int size = this.size;
      for (int i=0; modCount == expectedModCount && i < size; i++) {
          action.accept(elementData[i]);
      }
      
    • Iterator.forEachRemaining

      final Object[] elementData = ArrayList.this.elementData;
      if (i >= elementData.length) {
          throw new ConcurrentModificationException();
      }
      while (i != size && modCount == expectedModCount) {
          consumer.accept((E) elementData[i++]);
      }
      
    • Stream.forEach which will end up calling Spliterator.forEachRemaining

      if ((i = index) >= 0 && (index = hi) <= a.length) {
         for (; i < hi; ++i) {
             @SuppressWarnings("unchecked") E e = (E) a[i];
             action.accept(e);
         }
         if (lst.modCount == mc)
             return;
      }
      

    As you can see, the inner loop of the implementation code, where these operations end up, is basically the same, iterating over indices and directly reading the array and passing the element to the Consumer.

    Similar things apply to all standard collections of the JRE, all of them have adapted implementations for all ways to do it, even if you are using a read-only wrapper. In the latter case, the Stream API would even slightly win, Collection.forEach has to be called on the read-only view in order to delegate to the original collection’s forEach. Similarly, the iterator has to be wrapped to protect against attempts to invoke the remove() method. In contrast, spliterator() can directly return the original collection’s Spliterator as it has no modification support. Thus, the stream of a read-only view is exactly the same as the stream of the original collection.

    Though all these differences are hardly to notice when measuring real life performance as, as said, the inner loop, which is the most performance relevant thing, is the same in all cases.

    The question is which conclusion to draw from that. You still can return a read-only wrapper view to the original collection, as the caller still may invoke stream().forEach(…) to directly iterate in the context of the original collection.

    Since the performance isn’t really different, you should rather focus on the higher level design like discussed in “Should I return a Collection or a Stream?”

提交回复
热议问题