Well, the basic reason is that the people who coded collect() and Collectors.toList() were smart enough to find a way to ensure that the operation could get the correct result even if you use multiple threads. That's true of the other collectors defined in the Collectors class too. That's one of the reasons we like to use those classes.
In this particular case, you can imagine that if you split the work among just two threads, the thing to do would be to divide the work into two halves, in a way that you could combine the results later. If the original IntStream is supposed to go from 1-11, then maybe one
thread will do 1-6 and the other will do 7-11. Both threads filter out the odd numbers. And the first thread will make a List of 2,4. And the second thread makes a List of 6,8,10. And when both threads have finished that wok, then the two lists are combined into one List, knowing that the list from the first thread comes first, and the list from the second list comes second. So you get a list of 2,4,6,8,10.
Now in practice, there may be more than two threads. Or less, if the job is really short.
. But the principle is the same. Divide the work up, but make sure you do it in a way that you can recover the original order later.