자바에서 컬렉션을 병렬처리하기 위해 parallelStream api를 사용한다.
여기서 병렬 스트림을 효율적으로 사용하기 위해서는 해당 api를 사용하는 컬렉션이 어떤 컬렉션인지 중요하다.
결론만 말하자면 ArrayList 를 사용했을 때 병렬스트림의 효용을 잘 이끌어낼 수 있다.
가령 HashSet의 경우에는 병렬스트림을 사용하니만 못 한 결과를 낼 수 있다.
그 이유는 Spliterator가 HashSet의 버킷 테이블을 순회해서 각 sub 배열마다 어느 만큼의 데이터를 담을지에 대한 기대가 불분명하다.
HashSet의 경우 Spliterator를 HashMap.KeySpliterator를 사용한다.
public Spliterator<E> spliterator() {
return new HashMap.KeySpliterator<>(map, 0, -1, 0, 0);
}
이 spliterator는 HashSet 내부에서 저장된 버킷 배열의 인덱스를 기준으로 분할한다.
하지만, 버킷 배열의 특성상 해당 배열의 데이터들은 균등하게 존재하지 않습니다. 왜냐하면, HashSet에 데이터를 넣을 때 해당 데이터의 hash값을 계산한 후 해당 해시를 기반으로 인덱스가 정해지기 때문이다.
그래서 인덱스를 기반으로 나눈다한들 각 sub들은 데이터가 균등하게 존재하지 않고, 이는 병렬 처리에 불이익을 주게 된다.
이러한 이유로 HashSet은 Parallel Stream에 비친화적이고, Parallel Stream을 사용하려면 캐시 지역성과 sub stream들의 데이터 균등성을 고려하여 List를 사용하는 것이 바람직하다고 한다.