Thanks for the reply. Sorry my original post didn’t describe the question correctly. I modified the question a little bit, but I am not sure if your answer can still solve the problem?
The best way would be to use a cartesian function, but as far as I know the Kotlin standard library doesn’t have it out of the box. If it did you could write this example this way:
classA.itemsA
.flatMap { a -> classB.itemsB.map { a to it } }
.filter { (a, b) -> a.user == b.id }
.forEach { classA.doSmth() }
I think this would work, I haven’t tested it but the flatMap part should be one possible implementation of the cartesian function.
Also if you are just looking for different ways to write this you could use normal for loops instead of forEach (your example).
As a last note: The title says “optimize”. If you are looking at performance/memory your original code should be the best. All other options might perform as good but not better. If you use Sequences instead of the normal list version of flatMap, filter, etc you should be as performant but it wont be better. If you stick with lists it might be a bit worse depending on the number of items, especially if the temp list created by flatMap has to be resized multiple times – the resulting list of flatMap here might get really big if both of your original lists are big, but than sequences just skip that problem (itemsA.asSequence() and keep the rest as it is).
Another way to think about optimising is to consider changing data types. For example, if you know you’ll do this lookup more often than others, you might want to store your itemsA in a Map<String, List<Class1>>, where the String key is the id from the Class1 instance. Then you can use that hash lookup to find the instance with an id matching a given user very quickly.
If you have multiple different lookups you could handle them with maps external to the class, possibly in some Index class and/or behind extension functions.
This is the same idea as indexes in a database: you’re using more space, but gaining speed.