glenn-syj / more-effective-java

이펙티브 자바를 읽으며 자바를 더 효율적으로 공부합니다
4 stars 5 forks source link

[MEJ-011] Collector Characteristircs UNORDERED의 용도 #198

Open undeadtimo opened 3 months ago

undeadtimo commented 3 months ago

Based on item46 by @glenn-syj


감사합니다, glenn님의 간단한 예시들과 구체적인 설명으로 Collector에 대해 이해하게 되었습니다.

Supplier, Acuumulator, Combiner의 역할을 글로만 보았을 때는 감을 잡지 못하다가 예시 코드와 설명을 같이 보니 이해할 수 있었습니다.

첫 번째 예시 코드를 보면

Stringbuilder::new를 통해 스트림 요소들을 담아둘 Stringbuilder 객체를 생성하였고,

다음으로 Acuumulator 부분에서는 (sb, s) -> sb.append(s).append(", ") 코드가 사용되었는데,

Supplier 에서 생성한 Stringbuiler를 sb로, 변환할 스트림 요소를 s로 놓고 있군요.

Stringbuilder 객체에 s에 해당하는 요소를 넣고, ", " 를 추가하는 기능이 각 요소들에 적용되면,

combiner는 "apple, " , "banana, ", "cherry ," 이 세 String 요소들을 결합해주는 것이구요.

다만, Finisher에 해당하는 Collector.Characteristics.UNORDERED에 대한 기능이 어떤 역할을 하는 것인지 잘 이해가 되지 않아 찾아보았습니다.

데이터 수집 시에 순서에 구애받지 않고 요소를 처리할 수 있다.

저는 stream 병렬 처리라면 당연히 순서에 구애받지 않고 처리하고, 병렬 처리가 아니라면 순서에 따른 처리가 이루어지는 것이라 생각하였습니다.

그러나 어떤한 연산이 이루어지는가에 따라 결합법칙[ex) (a + b) + c = a + (b + c)]이 성립할 수도 성립하지 않을 수도 있는 것이기에 이 부분에 대한 명시가 필요합니다.

따라서, Collector.Characteristics.UNORDERED는 해당 연산이 결합법칙이 성립하기 때문에 순서에 상관없이 병렬 처리를 하도록 하여 처리 속도를 향상시키는 것이었습니다.

혹여 제가 조사한 부분이 옳지 않다면 지적 부탁드립니다.


Reference:

https://stackoverflow.com/questions/39942054/what-does-the-java-8-collector-unordered-characteristic-mean

glenn-syj commented 2 months ago

@undeadtimo 님께서 잘 말씀해주셨듯이, StringBuilder.append() 에 대해서는 결합 법칙이 성립하되 교환 법칙은 성립하지 않는다고 보는 게 맞습니다. 그러나 "결합 법칙이 성립하기 때문에 순서에 상관없이 병렬 처리"를 한다는 말은 어폐가 있는듯 보입니다. 그런데 이는 제가 예시 코드를 잘못 쓴 까닭으로 보이네요.

다시 생각해보자면 StringBuilder.append()는 병렬 스트림에서 이용한다면 교환 법칙이 성립하지 않아, 비결정적인(non-determinstic) 결과를 낼 것 같네요. 이러한 경우에는 사실 순서를 유지하는 수집기를 이용하거나, 순차적 스트림을 이용하는 게 맞는 것 같습니다.

다시 한 번 검토해주셔서, 저도 무심코 넘어갈 뻔한 잘못된 지식을 다시 생각해보게 되었네요!