Open undeadtimo opened 3 months ago
@undeadtimo 님께서 잘 말씀해주셨듯이, StringBuilder.append()
에 대해서는 결합 법칙이 성립하되 교환 법칙은 성립하지 않는다고 보는 게 맞습니다. 그러나 "결합 법칙이 성립하기 때문에 순서에 상관없이 병렬 처리"를 한다는 말은 어폐가 있는듯 보입니다. 그런데 이는 제가 예시 코드를 잘못 쓴 까닭으로 보이네요.
다시 생각해보자면 StringBuilder.append()
는 병렬 스트림에서 이용한다면 교환 법칙이 성립하지 않아, 비결정적인(non-determinstic) 결과를 낼 것 같네요. 이러한 경우에는 사실 순서를 유지하는 수집기를 이용하거나, 순차적 스트림을 이용하는 게 맞는 것 같습니다.
다시 한 번 검토해주셔서, 저도 무심코 넘어갈 뻔한 잘못된 지식을 다시 생각해보게 되었네요!
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