iterate help
# announcements
t
iterate help
s
I think you can do something like
Copy code
myObjects.filter { it.name == "foo" }.forEach{ //do something }
You could potentially use map instead of forEach too?
☝️ 1
👍 2
s
and if there's only one object with the name
foo
, you can do this:
Copy code
myObjects.find { it.name == "foo" }?.//do something
👍 1
t
@Steven McLaughlin @serebit do these methods help efficiency or just readability?
s
I'm not sure. In java, using those stream functions is much less efficient than just looping I believe.
s
Just readability, as far as I'm aware, although there might be some optimizations I'm not aware of
That being said, I know that using the iterator functions does not incur a performance penalty over a for-loop in most cases.
t
Any idea how they function differently than for-loops? Under-the-hood per say?
s
Using the Show Bytecode tool in IntelliJ, we can see the difference between the two methods in how they are executed.
👆 1
The first method, the for-in loop, looks like this in Kotlin:
Copy code
for (obj in myObjects) {
    if (obj == "bar") {
        print(obj)
    }
}
and it compiles down to this code in Java:
Copy code
Iterator var1 = myObjects.iterator();

      while(var1.hasNext()) {
         String obj = (String)var1.next();
         if (Intrinsics.areEqual(obj, "bar")) {
            System.out.print(obj);
         }
      }
The second method, if we use an optimization where we turn the thread into a Sequence before executing the transforms on it, looks like this in Kotlin:
Copy code
myObjects.asSequence().filter { it == "bar" }.forEach { println(it) }
and compiles down to this code in Java:
Copy code
Sequence $receiver$iv = SequencesKt.filter(CollectionsKt.asSequence((Iterable)myObjects), (Function1)null.INSTANCE);
      var1 = $receiver$iv.iterator();

      while(var1.hasNext()) {
         Object element$iv = var1.next();
         String it = (String)element$iv;
         System.out.println(it);
      }
So besides the sequence transform, the two are functionally the same.
✔️ 1
t
Amazing answer. So it really is just to cut down on the code you write and make it more readable.
s
Yep. There are some rare scenarios in which the generated bytecode is less efficient than a simple for-loop; but for the most part, it's a huge improvement in readability and functionality, with little to no sacrifice in performance.
s
Does the
asSequence()
actually make that more performant for smaller sets? The performance there depends on the size doesn't it? I think the sequence evaluates it lazily as opposed to eagerly if I remember correctly
s
Without
asSequence()
, the bytecode will generate a
while
loop for each operation performed on the set, and copy the result of each into a
destination
list. With
asSequence()
, each operation is performed in sequence on each individual member of the list, and so
asSequence()
does incur a significant performance benefit with multiple operations chained together.
If the set is small, the difference is negligible, but it's still good practice to use
asSequence()
regardless.
👍 1
s
Is there a reason they didn't make sequencing the default behavior if that's the case?
s
Sequencing doesn't work with all list operations, and isn't as intuitive. When you perform multiple transforms on a given collection, you expect each transform to apply to the entire list before moving onto the next transform. I'm not sure if that's the reason why it's not the default behavior, but that's what makes sense to me.
s
I found this article that seems to give some good information related to this in case anyone else comes looking at this thread later: https://blog.kotlin-academy.com/effective-kotlin-use-sequence-for-bigger-collections-with-more-than-one-processing-step-649a15bb4bf
👍 1
a
@Steven McLaughlin what do you mean with make it the default behavior?
s
The more I thought about it, the less it made sense to me. It was a naive thought
a
I guess
List<T>
is the "default" because it is used everywhere, but its just a matter of
sequenceOf(...)
vs
listOf(...)