DAO를 생성할 때 반환 타입으로는 어떤 것이 좋을까? 라는 생각에서 선정하게 되었습니다
길이가 0인 경우 null을 반환한다면?
👉 빈 컬렉션/배열을 할당하는데 비용이 든다는건 맞는 말이다.
하지만 이 정도 성능 차이는 신경을 써야할 수준은 아니다.빠른 프로그램보다 좋은 프로그램을 만들자
게다가 빈 컬렉션/배열은 새로 할당하지 않아도 반환할 수 있다.
public class Cars {
private final List<Car> value;
// AS-IS
public List<Car> getValueByNull() {
if (value.isEmpty()) {
return null;
}
return new ArrayList<>(value);
}
// TO-BE
public List<Car> getValue() {
return new ArrayList<>(value);
}
}
성능 차이가 궁금해서 getValueByNull
와 getValue
를 100000번 호출해서 시간을 측정해보았다. 측정할 때마다 다른 결과를 보인다.
# try 1
getValueByNull: 16
getValue: 15
# try 2
getValueByNull: 15
getValue: 16
# try 3
getValueByNull: 10
getValue: 16
# try 4
getValueByNull: 0
getValue: 0
isEmpty() 메서드로 인한 차이인가 싶어서 무조건 null을 반환하도록 시도해았지만 마찬가지로 결과가 항상 랜덤했다.
Collections.emptyList
, Collections.emptyMap
등을 활용할 수도 있다. 이 메서드를 꼭! 사용 해야한다는 의미는 아니다. 빈 불변 컬렉션 반환에 대해 최적화가 필요한 경우 도입하고 실제로 성능이 개선 되는지도 확인해보아야 한다.
현재 제가 자주 사용하고 있는 NamedParameterJdbcTemplate를 이용해 디버깅 해보았습니다.
public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations {
// ...
@Override
public <T> List<T> query(String sql, SqlParameterSource paramSource, RowMapper<T> rowMapper)
throws DataAccessException {
return getJdbcOperations().query(getPreparedStatementCreator(sql, paramSource), rowMapper);
}
}
public class RowMapperResultSetExtractor<T> implements ResultSetExtractor<List<T>> {
// ...
@Override
public List<T> extractData(ResultSet rs) throws SQLException {
List<T> results = (this.rowsExpected > 0 ? new ArrayList<>(this.rowsExpected) : new ArrayList<>());
int rowNum = 0;
while (rs.next()) {
results.add(this.rowMapper.mapRow(rs, rowNum++));
}
return results;
}
}