카테고리 없음

2024. 7. 11. (목) 슈퍼코딩 부트캠프 Day 34 / 주특기 3주차

태영9922 2024. 7. 11. 12:37

 

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