https://kotlinlang.org logo
Title
t

temp_man

11/19/2018, 8:59 PM
iterate help
s

Steven McLaughlin

11/19/2018, 9:01 PM
I think you can do something like
myObjects.filter { it.name == "foo" }.forEach{ //do something }
You could potentially use map instead of forEach too?
👍 2
☝️ 1
s

serebit

11/19/2018, 9:02 PM
and if there's only one object with the name
foo
, you can do this:
myObjects.find { it.name == "foo" }?.//do something
👍 1
t

temp_man

11/19/2018, 9:03 PM
@Steven McLaughlin @serebit do these methods help efficiency or just readability?
s

Steven McLaughlin

11/19/2018, 9:04 PM
I'm not sure. In java, using those stream functions is much less efficient than just looping I believe.
s

serebit

11/19/2018, 9:05 PM
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

temp_man

11/19/2018, 9:07 PM
Any idea how they function differently than for-loops? Under-the-hood per say?
s

serebit

11/19/2018, 9:10 PM
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:
for (obj in myObjects) {
    if (obj == "bar") {
        print(obj)
    }
}
and it compiles down to this code in Java:
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:
myObjects.asSequence().filter { it == "bar" }.forEach { println(it) }
and compiles down to this code in Java:
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

temp_man

11/19/2018, 9:17 PM
Amazing answer. So it really is just to cut down on the code you write and make it more readable.
s

serebit

11/19/2018, 9:18 PM
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

Steven McLaughlin

11/19/2018, 9:26 PM
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

serebit

11/19/2018, 9:28 PM
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

Steven McLaughlin

11/19/2018, 9:30 PM
Is there a reason they didn't make sequencing the default behavior if that's the case?
s

serebit

11/19/2018, 9:31 PM
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

Steven McLaughlin

11/19/2018, 9:34 PM
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

Andreas Sinz

11/19/2018, 9:40 PM
@Steven McLaughlin what do you mean with make it the default behavior?
s

Steven McLaughlin

11/19/2018, 9:41 PM
The more I thought about it, the less it made sense to me. It was a naive thought
a

Andreas Sinz

11/19/2018, 9:44 PM
I guess
List<T>
is the "default" because it is used everywhere, but its just a matter of
sequenceOf(...)
vs
listOf(...)