포스트

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
참고한 자료외부 출처 5

외부 출처

이 글은 저작권자의 CC BY 4.0 라이선스를 따릅니다.

댓글

아직 댓글이 없습니다