1. 컬렉션 프레임워크
- 적합한 용량인가?
- 상황에 맞게 사용하기 쉬운 구조인가?
- 자주 발생하는 로직이 무엇이냐에 따라 상황에 따라 적합한 자료구조가 다르다.
- 컬렉션 프레임워크
2. 두가지 근본 Structure
- Array 구조 : 연속적인 메모리 구조
- Node 구조 : 떨어져있는 자료들을 Node로 연결한 구조
|
Array 구조
|
Node 구조
|
장점
|
|
|
단점
|
|
|
3. Java List 구현하기
import java.util.ArrayList;
import java.util.List;
public class ListInterfaceTest {
public static void main(String[] args) {
//List 정의
List<String> fruitList = new ArrayList<>();
//add(element)
fruitList.add("Apple");
fruitList.add("Banana");
fruitList.add("Orange");
fruitList.add("Kiwi");
System.out.println(fruitList);
//출력 : [Apple, Banana, Orange, Kiwi]
//add(index, element)
fruitList.add(3, "Mango");
//인덱스와 요소를 같이 추가
//인덱스 번호에 요소가 있으면 뒤로 밀어내고 그자리에 새로운 요소 추가
System.out.println(fruitList);
//출력 : [Apple, Banana, Orange, Mango, Kiwi]
//remove(index)
fruitList.remove(3);
System.out.println(fruitList);
//출력 : [Apple, Banana, Orange, Kiwi]
//get(index)
String myFruit = fruitList.get(3);
System.out.println(myFruit);
//출력 : Kiwi
//set(index, element)
fruitList.set(0, "PineApple");
System.out.println(fruitList);
//출력 : [Apple, PineApple, Orange, Kiwi]
//size()
System.out.println(fruitList.size());
//출력 : 4
//isEmpty()
List<String> fruitList2 = new ArrayList<>();
System.out.println(fruitList.isEmpty());
//출력 : false
System.out.println(fruitList2.isEmpty());
//출력 : true
//contains(element)
System.out.println(fruitList.contains("Kiwi"));
//출력 : true
System.out.println(fruitList.contains("Apple"));
//출력 : false
//indexOf(element), Clear
String myFruit2 = "Orange";
System.out.println(fruitList.indexOf(myFruit2));
//출력 : 2
System.out.println(fruitList.indexOf("Apple"));
//출력 : -1 , 리스트에 요소가 없으면 -1 반환
fruitList.clear();
System.out.println(fruitList);
//출력 : []
}
}
- ArrayList와 LinkedList 성능 차이 비교해보기
//get 요청은 ArrayList의 성능이 좋음
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class ListGetPerformanceTest {
static final int SIZE = 100000;
public static void main(String[] args) {
//ArrayList 구현
List<Integer> integerList = new ArrayList<>();
for (int i = 0; i < SIZE; i++) {
integerList.add(i);
}
//LinkedList 구현
List<Integer> integerList2 = new LinkedList<>();
for (int i = 0; i < SIZE; i++) {
integerList2.add(i);
}
long startTime;
long endTime;
startTime = System.currentTimeMillis();
for (int i = 0; i < SIZE; i++) {
integerList.get(i);
}
endTime = System.currentTimeMillis();
System.out.println("ArrayList Get Performance : " + (endTime - startTime) + "ms");
startTime = System.currentTimeMillis();
for (int i = 0; i < SIZE; i++) {
integerList2.get(i);
}
endTime = System.currentTimeMillis();
System.out.println("LinkedList Get Performance : " + (endTime - startTime) + "ms");
}
}
//add, remove는 LinkedList가 성능이 좋음
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class ListInsertRemovePerformanceTest {
static final int SIZE = 100000;
public static void main(String[] args) {
long startTime;
long endTime;
//ArrayList -> 삽입, 삭제 시 전체를 지웠다가 다시 생성해야 하는 방식
List<Integer> integerList = new ArrayList<>();
startTime = System.currentTimeMillis();
for (int i = 0; i < SIZE; i++) {
integerList.add(i);
if (i % 5 == 0) integerList.remove(0);
}
endTime = System.currentTimeMillis();
System.out.println("ArrayList add/remove : " + (endTime - startTime) + "ms");
//LinkedList -> 삽입, 삭제 시 링크만 새로 연결하는 방식 -> ArrayList보다 빠름
List<Integer> integerList2 = new LinkedList<>();
startTime = System.currentTimeMillis();
for (int i = 0; i < SIZE; i++) {
integerList2.add(i);
if (i % 5 == 0) integerList2.remove(0);
}
endTime = System.currentTimeMillis();
System.out.println("LinkedList add/remove : " + (endTime - startTime) + "ms");
}
}
1. Java 컬렉션 Map, Set
- Map : Key-Value 형태 / Key를 통해 Value 검색
- Map은 인터페이스이기 때문에 HashMap/TreeMap으로 구현해야함
- HashMap 구현 테스트
import java.util.HashMap;
import java.util.Map;
public class MapInterfaceTest {
public static void main(String[] args) {
//Map 정의 -> Map<Key, Value>
Map<String, Integer> fruitMap = new HashMap<>();
//<과일이름, 수량>
//Map에 데이터 삽입 put(key, value)
fruitMap.put("Orange", 5);
fruitMap.put("Apple", 10);
fruitMap.put("Banana", 3);
fruitMap.put("Kiwi", 20);
System.out.println(fruitMap);
//출력 : {Apple=10, Kiwi=20, Orange=5, Banana=3}
//순서 상관없이 삽입됨
//get(key)
Integer appleCount = fruitMap.get("Apple");
Integer bananaCount = fruitMap.get("Banana");
System.out.println(appleCount); //출력 : 10
System.out.println(bananaCount); //출력 : 3
//containsKey(key) -> boolean
Boolean isApple = fruitMap.containsKey("Apple");
System.out.println(isApple); //출력 : true
Boolean isMango = fruitMap.containsKey("Mango");
System.out.println(isMango); //출력 : false
//remove(key)
fruitMap.remove("Apple");
System.out.println(fruitMap);
//출력 : {Kiwi=20, Orange=5, Banana=3}
//size()
System.out.println(fruitMap.size()); //출력 : 3
//KeySet()
System.out.println(fruitMap.keySet()); //출력 : [Kiwi, Orange, Banana]
}
}
- Set : 중복 없는 컬렉션 / 고유한 요소 검색
- HashSet, TreeSet 으로 구현 필요
- HashSet 구현 테스트
import java.util.HashSet;
import java.util.Set;
public class SetInterfaceTest {
public static void main(String[] args) {
//Set 인터페이스 구현
Set<String> fruitSet = new HashSet<>();
//add(element) -> 중복은 안됨 // List는 중복도 삽입 가능
fruitSet.add("apple");
fruitSet.add("banana");
fruitSet.add("orange");
fruitSet.add("pear");
System.out.println(fruitSet);
//출력 : [banana, orange, apple, pear]
//순서 중요하지 않음
//remove(element)
fruitSet.remove("apple");
System.out.println(fruitSet);
//출력 : [banana, orange, pear]
//contains(element)
System.out.println(fruitSet.contains("banana"));
//출력 : true
System.out.println(fruitSet.contains("apple"));
//출력 : false
//size(),isEmpty(),clear()
System.out.println(fruitSet.size()); //출력 : 3
System.out.println(fruitSet.isEmpty()); // 출력 : false
fruitSet.clear();
System.out.println(fruitSet.isEmpty());//출력 : true
System.out.println(fruitSet); //출력 : []
}
}
2. Hash 란 무엇인가?
- 임의의 크기를 가진 데이터를 고정된 크기의 고유한 값으로 변환하는 함수
- 데이터 무결성 검사, 데이터 암호화, 데이터 검색
3. HashMap, HashSet 동작 원리
- HashMap 동작 원리
1) map.put(key, value)
2) key.hashCode() = 일정한 정수
3) 일정한 정수 % Array size 나머지 연산하여 map에 삽입
4) get 실행 시 2), 3) 실행
5) 인덱스 값 찾아 value
- HashSet 동작 원리
HashMap과 비슷하지만 중복 삽입 불가
- 해시함수 테스트
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Objects;
public class HashTest {
public static String hashString(String input) {
try {
//MessageDigest 인스턴스 생성 (해시 알고리즘으로 SHA-256 선택)
MessageDigest digest = MessageDigest.getInstance("SHA-256");
//입력문자열을 바이트 배열로 변환하여 해시함수에 전달
byte[] hashBytes = digest.digest(input.getBytes(StandardCharsets.UTF_8));
//Base64로 인코딩하여 해시된 문자열 반환
return Base64.getEncoder().encodeToString(hashBytes);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args) {
String password = "q1w2e3r4t5";
String hashPassword = hashString(password);
System.out.println("원본 : " + password);
System.out.println("암호화 : " + hashPassword);
//출력 : 원본 : q1w2e3r4t5
//출력 : 암호화 : I7XtKaHoQJ9wZE5E+uuuea5ocxjv1xnZryn4SWsBaoE=
//데이터 검색을 위한 Hash
long hashCode = Objects.hashCode(password); //일정한 정수 반환
long hashCode2 = Objects.hashCode(new Customer("민철"));
long hashCode3 = Objects.hashCode(new VIPCustomer("아이유"));
System.out.println("Objects HashCode : " + hashCode);
//출력 : Objects HashCode : -2088475284
System.out.println("Objects HashCode Customer : " + hashCode2);
//출력 : Objects HashCode Customer : 412278927
System.out.println("Objects HashCode VIPCustomer : " + hashCode3);
//출력 : Objects HashCode VIPCustomer : 81675471
long hashCode4 = Objects.hashCode(new Customer("ID01", "민철"));
long hashCode5 = Objects.hashCode(new Customer("ID01", "철수"));
System.out.println("Objects HashCode : " + hashCode4);
System.out.println("Objects HashCode : " + hashCode5);
//출력 : Objects HashCode : 2241628
//hashCode4와 hashCode5가 다른 인스턴스인데 customerID를 기준으로
//Customer클래스에서 hashCode 함수를 오버라이딩 했기 때문에
//같은 해시코드 값 반환
}
}
#슈퍼코딩, #1:1관리형부트캠프, #백엔드, #backend, #백엔드공부, #개발공부, #백엔드개발자 #취준일기, #취준기록, #취뽀, #빡공, #HTML/CSS, #javascript, #react , #java, #spring