These two collectors work differently.
First, the Stream structure breaks the workload into independent fragments that can be processed in parallel (therefore, you do not need a special collection as a source, a synchronizedList not required).
When using a non-competitive collector, each piece will be processed by creating a local container (here, Map ) using the Collectors provider and accumulating in the local container (placing records). These partial results should be combined, i.e. One card will be placed in another to get the final result.
The parallel collector supports simultaneous accumulation, so only one ConcurrentMap will be created, and all streams will accumulate on this card at a time. Therefore, after completion, no merge step is required, since there is only one card.
Thus, both collectors are thread safe, but can have completely different performance characteristics depending on the task. If Streams workload is heavy before collecting the result, the differences may be small. If, as in your example, there is no corresponding work for the collection operation, the result largely depends on how often it is necessary to match the comparisons, i.e. The same key, and as a valid target, ConcurrentMap deals with competition in the parallel case.
If you basically have different keys, the step of merging a non-competitive collector can be as expensive as the previous one, destroying any advantage of parallel processing. But if you have many duplicate keys that require merging values, then competition on the same key can degrade the performance of parallel collectors.
So, there is no simple โbest answerโ (well, if there was such an answer, why bother adding another option). It depends on your actual work. You can use the expected scenario as a starting point to select it, but then you must measure real-life data. Since both are equivalent, you can change your choice at any time.