2021-05-16-TIL
2021-05-16-TIL
Enum 사용
상태나 종류처럼 정해진 값 집합은 문자열이나 정수 상수 대신 enum으로 표현한다. 오타가 컴파일 오류로 잡히고, 상수마다 필드와 메서드를 둘 수 있어 값에 딸린 로직을 enum 안에 모을 수 있다. 링크된 글들은 enum으로 분기문을 없애고 상태별 계산을 enum 상수 안에 넣는 예를 보여 준다. DB에 저장할 때 JPA의 @Enumerated(EnumType.ORDINAL)은 선언 순서(숫자)를 저장하므로, 중간에 상수를 추가하면 기존 데이터의 의미가 바뀐다. 이름을 저장하는 EnumType.STRING을 쓰는 편이 안전하다.
- https://jojoldu.tistory.com/137
- https://limkydev.tistory.com/66
LocalDateTime
Java 8의 java.time 패키지는 기존 Date, Calendar의 문제(가변 객체라 스레드 안전하지 않음, 0부터 시작하는 월 같은 혼란스러운 API)를 고친 날짜와 시간 API다. 모든 클래스가 불변이라 plusDays() 같은 메서드는 원본을 바꾸지 않고 새 객체를 돌려준다. LocalDate는 날짜만, LocalTime은 시간만, LocalDateTime은 시간대 없는 날짜와 시간을, ZonedDateTime은 시간대까지 담는다. 문자열로 바꿀 때는 DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")으로 형식을 정해 format()을 호출한다.
- https://jeong-pro.tistory.com/163
- https://java119.tistory.com/52
- https://mkyong.com/java8/java-8-how-to-format-localdatetime/
- https://a1010100z.tistory.com/91
LocalTime compareTo()
compareTo()는 두 시간을 비교해 앞이면 음수, 같으면 0, 뒤면 양수를 돌려준다. 조건문에서는 의미가 더 분명한 isBefore(), isAfter()를 쓰는 편이 읽기 쉽다.
- https://www.geeksforgeeks.org/localtime-compareto-method-in-java-with-examples/
LocalTime plusDays()
링크는 LocalDate의 plusDays()를 다룬다. LocalTime은 날짜 정보가 없어서 plusDays()가 없고 plusHours(), plusMinutes()만 있다. 시간을 더하다 자정을 넘으면 날짜 없이 다시 0시부터 이어진다. plusDays()는 지정한 일수를 더한 새 LocalDate를 반환하고 원본은 바뀌지 않는다.
- https://www.geeksforgeeks.org/localdate-plusdays-method-in-java-with-examples/#:~:text=The%20plusDays()%20method%20of,unaffected%20by%20this%20method%20call.
LocalDateTime to Date
LocalDateTime은 시간대가 없고 Date는 특정 순간(UTC 기준 밀리초)이므로, 바꾸려면 시간대를 정해야 한다. Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant())처럼 시간대를 붙여 Instant로 만든 뒤 변환한다.
- https://mkyong.com/java8/java-8-convert-localdate-and-localdatetime-to-date/
String to LocalDateTime
LocalDateTime.parse("2021-05-16T10:15:30")은 ISO-8601 형식을 기본으로 파싱한다. 다른 형식이면 LocalDateTime.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))처럼 포맷터를 넘긴다.
- https://www.java67.com/2016/04/how-to-convert-string-to-localdatetime-in-java8-example.html
ParseException
Date클래스에서 parse()메서드를 사용하면 발생할 수 있는 예외이다. 이 메서드를 사용하려면 무조건 이 예외에 대해서 처리해주어야한다. 하지만 LocalDateTime을 사용하면 별도로 처리해주지 않아도 자동으로 해준다.
정확히는 SimpleDateFormat.parse()가 던지는 ParseException이 checked 예외라서 반드시 try-catch나 throws로 처리해야 한다. LocalDateTime.parse()도 형식이 맞지 않으면 실패하지만, 이때 던지는 DateTimeParseException은 RuntimeException의 하위 클래스(unchecked)라 컴파일러가 처리를 강제하지 않는다. 예외가 사라진 것은 아니므로 사용자 입력을 파싱할 때는 여전히 잡아서 처리해야 한다.
- https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/text/ParseException.html
Stream에서 예외를 throw하는 방법
map()에 넘기는 Function의 apply()는 checked 예외를 선언하지 않으므로, 람다 안에서 checked 예외를 던지는 메서드를 부르면 컴파일되지 않는다. 람다 안에서 잡아서 unchecked 예외(UncheckedIOException이나 직접 만든 런타임 예외)로 감싸 다시 던지는 것이 일반적인 해법이다. unchecked 예외는 람다 밖으로 그대로 전파된다.
- https://www.python2.net/questions-1295762.htm
예외 처리
SLIPP의 예외 처리 질문 글이다(지금은 사이트가 응답하지 않아 내용을 다시 확인하지 못했다). 예외 처리에서 기본이 되는 기준은 Java 튜토리얼에 정리되어 있다. 호출한 쪽이 예외에서 합리적으로 복구할 수 있으면 checked 예외로, 복구할 수 없으면 unchecked 예외로 만든다. 잡은 예외를 그냥 삼키면 원인을 추적할 수 없으므로, 처리할 수 없다면 원인 예외를 담아 다시 던진다.
- https://www.slipp.net/questions/350
List to Map
Collectors.toMap(키함수, 값함수)로 리스트를 맵으로 바꾼다. 같은 키가 두 번 나오면 IllegalStateException이 나므로, 중복이 가능하면 세 번째 인자로 병합 함수((a, b) -> a)를 넘긴다. 키별로 여러 값을 모으려면 Collectors.groupingBy()를 쓴다.
1
2
Map<Long, User> byId = users.stream()
.collect(Collectors.toMap(User::getId, Function.identity(), (a, b) -> a));
- https://www.baeldung.com/java-list-to-map
- https://mkyong.com/java8/java-8-convert-list-to-map/
- https://dzone.com/articles/how-to-convert-list-to-map-in-java
List to Set
리스트를 집합으로 바꾸면 중복이 제거된다. new HashSet<>(list)가 가장 간단하고, 순서를 유지하려면 LinkedHashSet을 쓴다. 반대로 new ArrayList<>(set)으로 리스트로 바꾼다.
- https://www.baeldung.com/convert-list-to-set-and-set-to-list
댓글
아직 댓글이 없습니다