
<프리미티브 타입과 레퍼런스 타입>
프리미티브 타입(Primitive type)
- int, long, float, double 등
레퍼런스 타입(Reference type)
- Integer, Long, Float, Double 등
★ 기억하기
: 레퍼런스 타입은 참조형 변수이므로 프리미티브 타입보다 연산 속도가 더 느립니다.
정수형
- 나누기, 모듈러 연산 모두 소수점 버림
부동소수형
System.out.println(10.0 % 3.2) // 모듈러 / 0.39999999999~47
- 10.0 % 3.2 의 결과값이 0.4가 아니라 0.3999999~47
앱실론을 포함한 연산에 주의하기
- 위와 같은 결과의 원인: 자바는 부동소수형 데이터를 이진법으로 표현하기 때문 ⇒ 표현 과정에서 오차 발생 ⇒ 이를 앱실론(epsilon)이라고 함.
- 코테 부동소수형 데이터 다룰 때 앱실론 항상 생각하기
- 앱실론 때문에 0.3을 3번 더한 a의 값에서 0.3을 빼면 0이 아님!!
관련 포스팅 글 참고▼
[Java] 자바에서 앱실론(Epsilon)과 부동소수점 오차 검사
[Java] 자바에서 앱실론(Epsilon)과 부동소수점 오차 검사
부동소수점(Floating-Point) 수는 컴퓨터에서 실수를 표현하는 방식 중 하나입니다. 그러나 부동소수점은 근본적으로 정확하지 않기 때문에 미세한 오차가 발생할 수 있습니다. 이로 인해 두 부동소
yujinius45.tistory.com
- 부동소수형 데이터를 활용하는 문제는 오차 허용 범위를 언급하는 경우가 많으니 꼭 체크하기
public class EpsilonExample {
public static void main(String[] args) {
double a = 0.1 + 0.2;
double b = 0.3;
double epsilon = 1e-10; // 10의 -10승, 아주 작은 값
// ==로 비교하면 다른값으로 나옴 아래와 같이 비교하기
if (Math.abs(a - b) < epsilon) {
System.out.println("a와 b는 같은 값으로 간주됩니다."); // 이 코드가 출력됨
} else {
System.out.println("a와 b는 다른 값입니다.");
}
}
}
<컬렉션 프레임워크>
컬렉션 프레임워크란?
- 여러 개의 값을 저장하고 그 값을 쉬우면서 효율적으로 처리해주는 표준화 클래스의 집합
- 대표적 컬렉션 프레임워크: 리스트 ArrayList, 스택 Stack, 큐 Queue, 데크 ArrayDeque, 해시맵 HashMap 등이 있음
배열
- Arrays 클래스의 toString() 메서드 사용해 배열 요소 쉽게 출력하여 디버깅
System.out.println(Arrays.toString(array)); // [1,2,3]
배열의 인덱스
- 배열은 생성 후 크기 변경 불가
- 배열 생성 후 새 데이터 삽입, 삭제 불가, 기존 데이터만 변경 가능
- 인덱스를 이용한 배열 요소에 대한 접근, 변경 시간 복잡도는 O(1)
리스트
- 코테 기준으로 ArrayList
| 배열 | 리스트 | |
| 크기 | 고정 | 가변 |
| 삽입, 삭제 | 불가능 | 가능 |
- ArrayList 맨 뒤 새 데이터 추가 평균 시간 복잡도 O(1)
- 기존 데이터의 삭제, 중간에 데이터 삽입할 때 시간 복잡도 O(N)까지 커질 수 있음
// 리스트 객체 생성
ArrayList<Integer> list = new ArrayList<>();
// 값 추가
list.add(1);
list.add(2);
list.add(4);
System.out.println(list.get(2)); // 4, 인덱스로 값 접근
System.out.println(list); // [1, 2, 4]
-
- 리스트 출력은 바로 해도 됨! 배열에서는 Arrays.toString(arr) 썼는데
해시맵 hashmap
- key - value 쌍을 저장하는 해시 테이블로 구성
- 키를 사용하여 값을 검색하는 자료구조
해시맵 초기화
HashMap<String, Integer> map = new HashMap<>();
해시맵의 데이터 삽입과 출력
map.put("apple", 1);
map.put("banana", 2);
map.put("oragne", 3);
// 해시값 출력
System.out.println(map); // {banana=2, orange=3, apple=1}
해시맵의 데이터 검색
String key = "apple";
if(map.containsKey(key)){
int value = map.get(key);
System.out.println(key + ": " + value); // apple :1
}else{
// 키가 없는 경우 예외가 발생하므로 예외처리를 해줘얗 ㅏㅁ
System.out.println(key +"는 해시맵에 없음");
}
- 참고: 자바에는 해시맵과 유사하지만 키-쌍 저장 말고 값 없이 키만 저장하는 해시셋도 있음
문자열
- 문자열은 문자들을 배열의 형태로 구성한 이뮤터블 객체
문자열 초기화
- 자바에서 문자열은 이뮤터블 객체
- 이뮤터블 객체: 값을 변경할 수 없는 객체 의미
- 시간 복잡도 관점에서 이뮤터블 객체 사용은 주의해야 함
String str = "hello";
💡 기억하기!!!!
문자열은 문자들을 배열의 형태로 구성한 이뮤터블 객체
- 이뮤터블 객체: 값을 변경할 수 없는 객체 의미
- 시간 복잡도 관점에서 이뮤터블 객체 사용은 주의해야 함
문자열 추가, 삭제
- 문자열은 Immutable 객체이므로 기존 객체를 수정하는 것이 아닌 새로운 객체를 반환함
- 문자열 길이 N일 때 O(N)이 됨
String string = "He";
string += "llo";
System.out.println(string); // Hello
문자열 수정
string.replace("수정할 것", "수정되어 들어갈 것");
StringBuffer & StringBuilder
- StringBuffer, StringBuilder 클래스는 뮤터블하므로 값을 변경할 때 시간복잡도 더 효율적
long start = System.currentTimeMillis();
StringBuilder s = new StringBuilder();
for(int i = 1; i <=10000; i++){
s.append(i);
}
long end = System.currentTimeMillis();
System.out.println(((end - start) / 1000.0)+"초");
- String으로 수행했다면 O(N^2)
- String 값을 변경하는 연산이 많을 때는 효율이 높은 StringBuilder, StringBuffer 사용
- 두 클래스의 차이는 멀티 스레드 환경에서 Thread-Safe 여부로 나눔
- 코테에서는 다수의 스레드 생성 필요 x ⇒ Thread-Safe가 없는 StringBuilder 클래스가 속도 측면에서 미세하지만 더 빠르므로 StringBuilder 사용하기
- Thread-Safe한 클래스는 동기화를 통해 데이터의 일관성을 유지합니다.
특성 String StringBuffer StringBuilder Immutable 예 아니요 아니요 Thread-Safe 예 예 아니요 성능 상대적으로 느림 상대적으로 빠름 가장 빠름
StringBuilder 클래스의 활용 방법 ★
- String 값을 변경하는 연산이 많을 때는 시간 초과가 발생하지 않도록 꼭 String 대신 StringBuilder 사용하기!
// StringBuilder 객체 생성
StirngBuilder sb = new StringBuilder();
// 문자열 Add
sb.append(10);
sb.append("ABC");
// 출력
System.out.println(sb); // 10ABC
sb.deleteCharAt(3); // 3번째 인덱스 문자 제거
System.out.println(sb); // 10AC
sb.insert(1, 2); // 1번째 인덱스에 2라는 문자 추가
System.out.println(sb); // 120AC
<메서드>
메서드 정의
public int fun_name(int param1, int param2){
// 실행 코드
return result; // 반환값
}
메서드 호출
public static void main(String[] args){
int ret = add(2, 3);
}
<람다식>
- 람다식(lambda expression)은 자바 1.8버전에서 추가됨
- 람다식은 다른 말로 익명 함수(anonymous function)이라고도 함
- 익명 함수란?
- 이름이 없는 함수
- 코드에서 딱 한 번 실행할 목적으로 사용하거나 함수 자체를 다른 함수의 인수로 전달할 때 사용
람다식의 정의와 사용
private static class Node{
int dest, cost;
public Node(int dest, int cost){
this.dest = dest;
this.cost = cost;
}
}
public static void main(String[] args){
Node[] nodes = new Node[5];
node[0] = new Node(1, 10);
node[1] = new Node(2, 20);
node[2] = new Node(3, 15);
node[3] = new Node(4, 5);
node[4] = new Node(5, 25);
Arrays.sort(nodes, (o1, o2) -> Integer.compare(o1.cost, o2.cost)); // ①
Arrays.sort(nodes, new Comparator<Node>(){
@Override
public int compare(Node o1, Node o2){
return Integer.compare(o1.cost, o2.cost);
}
}); // ②
}
- 위 코드에서 ①, ② 동일 로직 수행, 정렬 API 사용할 때 좋음
Integer.compare(int x, int y) 메서드
- x < y 면 -1 반환
- x > y 면 1 반환
- x == y면 0 반환
- 간혹 정렬 조건 구현시 [x-y]와 같이 뺄셈하는 경우 오버플로우 위험이 있으므로 compare()메서드 사용이 좋음
<코딩 테스트 코드 구현 노하우>
조기 반환 early return
- 코드 실행 과정이 함수 끝까지 도달 전 반환하는 기법
- 가독성 up, 예외 처리 good, 깔끔
보호 구문 guard clauses
- 로직 진행하기 전 예외 처리 코드를 추가하는 기법
- 조건문을 이용해 초기 입력값이 유효한지 검사하고 그렇지 않으면 바로 함수 종료하는 보호 구문 쓸 수 있음
import java.util.List;
static double calculateAverage(List<Integer> numbers){
if(numbers == null){
return 0; // null이면 종료
}
if(numbers.isEmpty()){
return 0; // 데이터 없으면 종료
}
int total = numbers.stream().mapToInt(i->i).sum(); //예외처리 후 기능 구현
return (double) total / numbers.size();
}
제네릭 generic
- 빌드 레벨에서 타입 체크를 하여 타입 안정성을 제공
- 타입 체크와 형변환을 생략할 수 있게 해주어 코드를 간결하게 만들어주는 기능
List list = new ArrayList()
list.add(10);
list.add("abc");
int sum1 = (int) list.get(0) + (int) list.get(1); // 런타임 오류
List<Integer> genericList = new ArrayList<>();
// ▲ 리스트 정의할 때 타입 강제하는 것이 제네릭
// 제네릭은 타입에 맞지 않는 데이터 추가할 때 문법 오류를 발생시킴
genericList.add(10);
genericList.add("abc"); // 문법(빌드 레벨) 오류 발생
int sum2 = genericList.get(0) + genericList.get(1);
- 제네릭으로 작성했는데 문제가 있으면 빌드 자체가 안되므로 런타임 버그 방지 가능
- 또한, 데이터 접근하여 사용할 때 형변환 할 필요 없어 코드 간결해짐
💡 코테에서는 여러 타입의 데이터를 하나의 컬렉션에 넣어야 하는 경우는 거의 없으므로 제네릭 타입을 강제하여 실수를 방지하는 것이 좋음
기억하기
- 자바의 데이터 타입에는 프리미티브 타입과 레퍼런스 타입이 있다. 프리미티브 타입의 연산 속도가 레퍼런스 타입에 비해 더 빠르기 때문에 가능함녀 프리미티브 타입 사용하는 것이 좋다.
- 자바의 컬렉션 프레임워크의 리스트, 해시맵은 코딩 테스트에서 자주 사용하므로 꼭 알아두면 좋다.
- 자바에서 String 클래스의 객체는 Immutable 객체이다. 값을 변경할 수 없기 때문에 + 연산 등으로 값을 변경할 경우 효율이 좋지 않다. String의 + 연산이 자주 발생한다면 StringBuilder를 사용하자.
- 메서드는 길어질 수 있는 코드를 논리적으로 분리할 수 있게 해준다. 잘 활용하면 코드의 중복을 줄이고 가독성을 높일 수 있다.
- 조기 반환, 보호 구문, 제네릭 등의 기법을 활요하면 코드의 가독성과 효율성을 높일 수 있다.
해당 글은 다음 책을 참고하여 공부하며 정리한 글입니다.
https://ebook-product.kyobobook.co.kr/dig/epd/ebook/E000006973689
코딩 테스트 합격자 되기: 자바 편 | 김희성 | 골든래빗(주)- 교보ebook
자료구조, 알고리즘, 빈출 97 문제로 대비하는 코테 풀 패키지(모의고사, 엄친아 손노트, 온라인 학습 지원 제공) , ★ 빈출문제 97개면 코딩 테스트 합격할 수 있어요! ★ 자료구조, 알고리즘 이론
ebook-product.kyobobook.co.kr
'코딩테스트 > 코딩 테스트 합격자 되기 : 자바편' 카테고리의 다른 글
| [코딩 테스트 합격자 되기 : 자바 편] 5. 배열(Array), ArrayList 기본 문법 개념 정리 (0) | 2024.06.03 |
|---|---|
| [코딩 테스트 합격자 되기 : 자바 편] 2. 프로그래머스 채점 기준 + 3. 알고리즘의 효율 분석 (0) | 2024.05.31 |
| [코딩 테스트 합격자 되기 : 자바 편] 1. 코딩 테스트 사전 준비 - [부제] Python에서 Java로 바꾸는 사람 나야나 (1) | 2024.05.31 |