memoRepository.findAllByTag(searchString, orderBy).stream()
.map(MemoListDto::new)
.toList();
// .collect(Collectors.toList())
위 코드는 tag를 이용해 메모를 검색하는 코드의 일부분이다.
마지막줄의 .toList 와 .collect(Collectors.toList()) 는 모두 List<MemoListDto> 를 반환해주는 것으로 보인다.
그러나, Stream.toList()의 내부 코드는
default List<T> toList() {
return (List<T>) Collections.unmodifiableList(new ArrayList<>(Arrays.asList(this.toArray())));
}
다음과 같이 unmodifiableList 를 반환하고 있다. 즉, 내부 값을 변경할 수 없는 List를 반환한다.
Collectors.collect() 코드도 살펴보자.
public static <T>
Collector<T, ?, List<T>> toList() {
return new CollectorImpl<>(ArrayList::new, List::add,
(left, right) -> { left.addAll(right); return left; },
CH_ID);
}
정확한 동작은 위 코드만으로 파악하기 어렵다. 주석을 보면,
Returns a Collector that accumulates the input elements into a new List. There are no guarantees on the type, mutability, serializability, or thread-safety of the List returned; if more control over the returned List is required, use toCollection(Supplier).
Returns: a Collector which collects all the input elements into a List, in encounter order
타입, 변화 가능성, 직렬화 가능성, 쓰레드 안전과 같은 부분에서 보장받지 못하는 List 를 반환한다는 것을 알 수 있다.
sonarlint 역시 java 17 부터 지원되는 Stream.toList() 를 사용할 것을 권하고 있고, 상황에 따라 다르겠지만 변경이 일어나지 않으면 Stream.toList() 를 사용하자.