Avatar
๐Ÿ˜‰

Organizations

  • ๋ชจ์˜ ํ…Œ์ŠคํŠธ

    ๋‘๊ฐœ ๋ฝ‘์•„์„œ ๋”ํ•˜๊ธฐ

    public static int[] solution_03(int[] numbers) {
        TreeSet<Integer> result = new TreeSet<>();
    
        for (int i = 0; i < numbers.length - 1; i++) {
            for (int j = i + 1; j < numbers.length; j++) {
                result.add(numbers[i] + numbers[j]);
            }
        }
    
        return result.stream().sorted().mapToInt(Integer::intValue).toArray();
    }
    
    • stream ์‚ฌ์šฉ๋ฒ•

    ๋ชจ์˜๊ณ ์‚ฌ (์ˆ˜ํฌ์ž)

    public static int[] solution_04(int[] answers) {
        int[] pattern1 = {1, 2, 3, 4, 5};
        int[] pattern2 = {2, 1, 2, 3, 2, 4, 2, 5};
        int[] pattern3 = {3, 3, 1, 1, 2, 2, 4, 4, 5, 5};
    
        int[] scores = new int[3];
    
        for (int i = 0; i < answers.length; i++) {
            scores[0] += answers[i] == pattern1[i % pattern1.length % pattern1.length] ? 1 : 0;
            scores[1] += answers[i] == pattern2[i % pattern2.length % pattern2.length] ? 1 : 0;
            scores[2] += answers[i] == pattern3[i % pattern3.length % pattern3.length] ? 1 : 0;
        }
    
        int maxScore = Arrays.stream(scores).max().getAsInt();
    
        ArrayList<Integer> answer = new ArrayList<>();
        for (int i = 0; i < scores.length; i++) {
            if (scores[i] == maxScore) {
                answer.add(i + 1);
            }
        }
        return answer.stream().mapToInt(Integer::intValue).toArray();
    }
    
    • ํŒจํ„ด ํŒŒ์•…, maxScore ๊ตฌํ•˜๋Š” ๋ฐฉ๋ฒ• .max().getAsInt()

    ํ–‰๋ ฌ์˜ ๊ณฑ์…‰

    public static int[][] solution_05(int[][] arr1, int[][] arr2) {
        int[][] answer = new int[arr1.length][arr2[0].length];
    
        for (int i = 0; i < arr1.length; i++) {
            for (int j = 0; j < arr2[0].length; j++) {
                for (int k = 0; k < arr1[0].length; k++) {
                    answer[i][j] += arr1[i][k] * arr2[k][j];
                }
            }
        }
        return answer;
    }
    
    • O(N^3) ์˜ index ์œ ์˜

    ์‹คํŒจ์œจ

    public static int[] solution_06(int N, int[] stages) {
    
        int[] challenger = new int[N+2];
        Arrays.stream(stages).forEach(stage -> challenger[stage]++);
    
        HashMap<Integer, Double> fails = new HashMap<>();
        double totalPlayer = stages.length;
    
        for( int i = 1; i <= N; i++) {
            if(challenger[i] == 0) {
                fails.put(i, 0.0);
            }else {
                fails.put(i, (double)challenger[i]/totalPlayer);
                totalPlayer -= challenger[i];
            }
        }
    
        return fails.entrySet().stream()
            .sorted((o1, o2) -> Double.compare(o2.getValue(), o1.getValue()))
            .mapToInt(HashMap.Entry::getKey).toArray();
    }
    
    • challenger ์„ [N+2] ๊ฐœ๋กœ ์žก๋Š” ์ด์œ 
    • for๋ฌธ์—์„œ totalPlayer -= challenger[i];
    • HashMap์˜ entrySet ์‚ฌ์šฉ ์š”๋ น ๊ธฐ์–ตํ•˜๊ธฐ

    ๋ฐฉ๋ฌธ ๊ธธ์ด

    import java.util.HashMap;
    import java.util.HashSet;
    
    class Solution {
    
        private static HashMap<Character, int[]> location = new HashMap<>();
    
        private static void initLocation() {
            location.put('U', new int[]{0, 1});
            location.put('D', new int[]{0, -1});
            location.put('L', new int[]{-1, 0});
            location.put('R', new int[]{1, 0});
        }
    
        public int solution(String dirs) {
            initLocation();
            int x = 5, y = 5;
    
            HashSet<String> answer = new HashSet<>();
    
            for (int i = 0; i < dirs.length(); i++) {
                int[] move = location.get(dirs.charAt(i));
                int nx = x + move[0];
                int ny = y + move[1];
    
                if (!isValidMove(nx, ny)) {
                    continue;
                }
                answer.add(x + " " + y + " " + nx + " " + ny);
                answer.add(nx + " " + ny + " " + x + " " + y);
    
                x = nx;
                y = ny;
            }
    
            return answer.size() / 2;
        }
    
        private static boolean isValidMove(int nx, int ny) {
            return nx < 11 && nx >= 0 && ny < 11 && ny >= 0;
        }
    }
    
    • A->B, B->A ๋„ ํ•˜๋‚˜์˜ ์ด๋™๊ฒฝ๋กœ๋กœ ํŒŒ์•…๋˜๋Š” ์  ์œ ์˜ answer.size() / 2 (๋ฌธ์ œ์—๋Š” ์ƒ์„ธ ์„ค๋ช…์ด ์—†์Œ)
    Created Thu, 24 Apr 2025 20:48:45 +0900
  • Virtual Thread๋Š” Java 19๋ถ€ํ„ฐ ๋„์ž…๋˜๊ณ  Java 21์—์„œ ์ •์‹์œผ๋กœ ์•ˆ์ •ํ™”๋œ Project Loom์˜ ํ•ต์‹ฌ ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜๋กœ, ๊ธฐ์กด์˜ Java ํ”Œ๋žซํผ์—์„œ ์‚ฌ์šฉ๋˜๋˜ platform thread(๋˜๋Š” OS thread)์™€๋Š” ๋‹ค๋ฅธ ๊ฐœ๋…์ž…๋‹ˆ๋‹ค. Virtual thread๋Š” **๊ฒฝ๋Ÿ‰ ์Šค๋ ˆ๋“œ(lightweight thread)**๋กœ์„œ, ์ˆ˜์‹ญ๋งŒ ๊ฐœ์˜ ์Šค๋ ˆ๋“œ๋ฅผ ๋™์‹œ์— ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค.


    1. Virtual Thread์˜ ํ•ต์‹ฌ ๊ฐœ๋…

    ๊ธฐ์กด Platform Thread vs Virtual Thread

    ํ•ญ๋ชฉ Platform Thread Virtual Thread
    ๊ตฌํ˜„ OS ๋ ˆ๋ฒจ์—์„œ ๊ด€๋ฆฌ JVM์—์„œ ์ง์ ‘ ๊ด€๋ฆฌ
    ์ƒ์„ฑ ๋น„์šฉ ๋ฌด๊ฒ๊ณ  ๋ฆฌ์†Œ์Šค ๋งŽ์ด ์‚ฌ์šฉ ๊ฐ€๋ณ๊ณ  ๊ฑฐ์˜ ๋ฌด์ œํ•œ ์ƒ์„ฑ ๊ฐ€๋Šฅ
    ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ OS ์Šค์ผ€์ค„๋Ÿฌ์— ์˜์กด JVM ์Šค์ผ€์ค„๋Ÿฌ ์‚ฌ์šฉ (๋น ๋ฆ„)
    ๋™์‹œ์„ฑ ์ฒ˜๋ฆฌ ์ œํ•œ์ ์ธ ๋™์‹œ์„ฑ ๊ณ ๋ฐ€๋„ ๋™์‹œ์„ฑ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ

    2. ์ฃผ์š” ํŠน์ง•

    ๊ฒฝ๋Ÿ‰ ์Šค๋ ˆ๋“œ

    • Virtual thread๋Š” ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ํ›จ์”ฌ ์ ๊ณ  ์ƒ์„ฑ ์†๋„๋„ ๋น ๋ฆ…๋‹ˆ๋‹ค.
    • 1:1 ๋งคํ•‘์ด ์•„๋‹Œ M:N ๊ตฌ์กฐ๋กœ, ์—ฌ๋Ÿฌ virtual thread๊ฐ€ ํ•˜๋‚˜์˜ OS thread๋ฅผ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค.

    ์ฐจ๋‹จ I/O์™€์˜ ํ†ตํ•ฉ

    • ๊ธฐ์กด์—๋Š” Thread.sleep()์ด๋‚˜ InputStream.read() ๊ฐ™์€ blocking I/O ํ˜ธ์ถœ์ด OS thread๋ฅผ ์ ์œ ํ•˜์—ฌ ๋น„ํšจ์œจ์ ์ด์—ˆ์Œ.
    • Virtual thread์—์„œ๋Š” ์ด๋Ÿฌํ•œ ํ˜ธ์ถœ์ด ๋ฐœ์ƒํ•˜๋ฉด JVM์ด ํ•ด๋‹น virtual thread๋ฅผ parkingํ•˜๊ณ , ๋‹ค๋ฅธ ์ž‘์—…์„ ์‹คํ–‰์‹œ์ผœ ๋ณ‘๋ชฉ์„ ํ”ผํ•จ.

    ์ฝ”๋“œ ์Šคํƒ€์ผ ์œ ์ง€

    • ๊ธฐ์กด์˜ CompletableFuture, Reactive API ์—†์ด๋„ ์ „ํ†ต์ ์ธ ๋™๊ธฐ ์ฝ”๋“œ ์Šคํƒ€์ผ์„ ์œ ์ง€ํ•˜๋ฉด์„œ๋„ ๊ณ ์„ฑ๋Šฅ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅ.

    3. ์‚ฌ์šฉ ์˜ˆ์‹œ

    Runnable task = () -> {
        System.out.println("Hello from " + Thread.currentThread());
    };
    
    Thread thread = Thread.ofVirtual().start(task);
    

    ํ˜น์€ Executors๋ฅผ ํ†ตํ•ด ์ˆ˜๋งŽ์€ ์Šค๋ ˆ๋“œ ์ฒ˜๋ฆฌ๋„ ๊ฐ€๋Šฅ:

    Created Thu, 24 Apr 2025 11:26:42 +0900
  • ๋Œ€์šฉ๋Ÿ‰ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ **๋น„๋™๊ธฐ Event Driven Architecture (EDA)**๋Š” ์‹œ์Šคํ…œ์ด ์ด๋ฒคํŠธ(event)๋ฅผ ์ค‘์‹ฌ์œผ๋กœ ์ž‘๋™ํ•˜๋ฉฐ, ํ™•์žฅ์„ฑ, ์œ ์—ฐ์„ฑ, ์„ฑ๋Šฅ์„ ํ™•๋ณดํ•˜๋Š” ๋ฐ์— ํšจ๊ณผ์ ์ธ ์•„ํ‚คํ…์ฒ˜์ž…๋‹ˆ๋‹ค. ์•„๋ž˜์— ๊ฐœ๋…๊ณผ ๊ตฌ์„ฑ ์š”์†Œ, ์žฅ์  ๋ฐ ์ ์šฉ ์‚ฌ๋ก€์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์„ค๋ช…๋“œ๋ฆด๊ฒŒ์š”.


    โœ… 1. ๊ธฐ๋ณธ ๊ฐœ๋…

    **Event Driven Architecture (EDA)**๋Š” ์‹œ์Šคํ…œ ๋‚ด์—์„œ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด, ์ด๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ์ฒ˜๋ฆฌํ•˜๋Š” ๊ตฌ์กฐ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค. ์ด๋ฒคํŠธ๋Š” ์–ด๋–ค ์ƒํƒœ์˜ ๋ณ€ํ™”๋ฅผ ์˜๋ฏธํ•˜๊ณ , ์ด๋ฅผ **ํ”„๋กœ๋“€์„œ(์ƒ์‚ฐ์ž)**๊ฐ€ ๋ฐœ์ƒ์‹œํ‚ค๊ณ , **์ปจ์Šˆ๋จธ(์†Œ๋น„์ž)**๊ฐ€ ์ด๋ฅผ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

    ๋น„๋™๊ธฐ ๋ฐฉ์‹์—์„œ๋Š” ์ด ์ด๋ฒคํŠธ๊ฐ€ ์ฆ‰์‹œ ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š๊ณ , ํ๋‚˜ ๋ฒ„ํผ๋ฅผ ํ†ตํ•ด ์ผ์‹œ ์ €์žฅ๋˜๋ฉฐ, ์ปจ์Šˆ๋จธ๊ฐ€ ๊ฐ€๋Šฅํ•œ ์‹œ์ ์— ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ตฌ์กฐ๋Š” ์‹œ์Šคํ…œ์ด ์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ๋ฐ์ดํ„ฐ๋‚˜ ์š”์ฒญ์ด ๋งŽ์„ ๋•Œ ๋ถ€ํ•˜๋ฅผ ์™„ํ™”ํ•˜๊ณ  ํ™•์žฅ์„ฑ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

    Created Thu, 24 Apr 2025 11:22:53 +0900
  • JPA์—์„œ N+1 ๋ฌธ์ œ๋Š” ์„ฑ๋Šฅ ์ €ํ•˜๋ฅผ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ๋Š” ๋Œ€ํ‘œ์ ์ธ ORM ์‚ฌ์šฉ ์‹œ์˜ ์ด์Šˆ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ์•„๋ž˜์— ์ž์„ธํžˆ ์„ค๋ช…๋“œ๋ฆด๊ฒŒ์š”.


    N+1 ๋ฌธ์ œ๋ž€?

    N+1 ๋ฌธ์ œ๋Š” JPA์—์„œ ์—ฐ๊ด€๋œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ง€์—ฐ ๋กœ๋”ฉ(LAZY loading) ๋ฐฉ์‹์œผ๋กœ ์กฐํšŒํ•  ๋•Œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

    ์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ƒํ™ฉ์„ ๊ฐ€์ •ํ•ด ๋ด…์‹œ๋‹ค:

    • ๊ฒŒ์‹œ๊ธ€(Post)๊ณผ ์ž‘์„ฑ์ž(Member)๋Š” ๋‹ค๋Œ€์ผ(N:1) ๊ด€๊ณ„์ด๋‹ค.
    • ๊ฒŒ์‹œ๊ธ€ 1๊ฐœ๋Š” ์ž‘์„ฑ์ž 1๋ช…์„ ๊ฐ€์ง„๋‹ค.
    @Entity
    public class Post {
        @ManyToOne(fetch = FetchType.LAZY)
        private Member author;
    }
    

    ๊ฒŒ์‹œ๊ธ€ ๋ฆฌ์ŠคํŠธ๋ฅผ ์กฐํšŒํ•˜๋Š” ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ฆฌ๋ฉด:

    List<Post> posts = postRepository.findAll();
    

    ์ด๋•Œ JPA๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค:

    Created Wed, 23 Apr 2025 20:48:45 +0900
  • stream().mapToInt()๋Š” Java Stream API์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๋ฉ”์„œ๋“œ ์ค‘ ํ•˜๋‚˜๋กœ, Stream์˜ ์š”์†Œ๋ฅผ intํ˜• ์ •์ˆ˜๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ IntStream์„ ์ƒ์„ฑํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

    ๐Ÿ’ก ์‚ฌ์šฉ ๋ชฉ์ 

    mapToInt()๋Š” ์ฃผ๋กœ ๊ฐ์ฒด ์ŠคํŠธ๋ฆผ์—์„œ ์ •์ˆ˜๊ฐ’์„ ์ถ”์ถœํ•˜๊ณ ์ž ํ•  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์–ด๋–ค ๊ฐ์ฒด ๋ฆฌ์ŠคํŠธ์—์„œ ํŠน์ • ํ•„๋“œ(์˜ˆ: ๋‚˜์ด, ์ ์ˆ˜ ๋“ฑ)๋ฅผ ์ •์ˆ˜๋กœ ๋ฝ‘์•„๋‚ผ ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.


    ๐Ÿ“Œ ๊ธฐ๋ณธ ๊ตฌ์กฐ

    Stream<T> stream = ...;
    IntStream intStream = stream.mapToInt(element -> ๋ณ€ํ™˜ํ•  int ๊ฐ’);
    

    โœ… ์˜ˆ์‹œ

    List<String> list = List.of("1", "2", "3");
    int sum = list.stream()
                  .mapToInt(Integer::parseInt)  // String โ†’ int
                  .sum();                       // IntStream ์—ฐ์‚ฐ ์‚ฌ์šฉ
    System.out.println(sum); // ์ถœ๋ ฅ: 6
    

    ์œ„ ์ฝ”๋“œ์—์„œ:

    Created Wed, 23 Apr 2025 13:48:45 +0900
  • ๋ฐฐ์—ด

    ์„ ์–ธ

    int[] arr = {0,0,0,0,0,0};
    int[] arr = new int[6];
    
    • ArrayList - ์ €์žฅํ•  ๋ฐ์ดํ„ฐ ๊ฐœ์ˆ˜๋ฅผ ์ •ํ™•ํžˆ ์•Œ ์ˆ˜ ์—†๋‹ค๋ฉด…

    ์ฐจ์›

    • 2์ฐจ์›
    int[][] arr = { {1,2,3}, {4,5,6}};
    

    ArrayList

    • ์ถ”๊ฐ€
    ArrayList<Integer> list = new ArrayList<>();
    list.add(1);
    
    • ์ดˆ๊ธฐํ™”
    ArrayList<Integer> list = new ArrayList<>();
    ArrayList<Integer> list2 = new ArrayList<>(list);
    
    • ์ ‘๊ทผ - get(index)
    • ์‚ญ์ œ - remove()

    • length ๋ณ€์ˆ˜
    • Arrays.sort()
    • toString()
    • size()
    • isEmpty()
    • Collections.sort
    ArrayList<Integer> list = new ArrayList<>(Arrays.asList(1,2,3,4,5));
    Collections.sort(list); // array๋Š” Arrays.sort()
    
    • sort() ์‚ฌ์šฉ์‹œ from ์ธ๋ฑ์Šค, to ์ธ๋ฑ์Šค๋กœ ํŠน์ •๋ฒ”์œ„๋งŒ ์ •๋ ฌ ๊ฐ€๋Šฅ

    ArrayList ํšจ์œจ์„ฑ

    • ์‹œ๊ฐ„ ๋ณต์žก๋„
    • ์ ‘๊ทผ O(1)
    • ๋งจ ๋’ค ์‚ฝ์ž… O(1)
    • ๋งจ ์•ž์ด๋‚˜ ์ค‘๊ฐ„. O(N)
    • ๊ณ ๋ คํ•  ์ 
      • ํ• ๋‹นํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”๋ชจ๋ฆฌ - ์ •์ˆ˜ํ˜• 1์ฐจ์› 1000๋งŒ๊ฐœ, 2์ฐจ์›์€ 3000*3000 ์ •๋„
      • ์ค‘๊ฐ„์— ๋ฐ์ดํ„ฐ ์‚ฝ์ž…์ด ๋นˆ๋ฒˆํ•œ ๊ฒฝ์šฐ ์‹œ๊ฐ„ ์ดˆ๊ณผํ•  ์ˆ˜ ์žˆ์Œ.

    ๋ชธํ’€๊ธฐ ๋ฌธ์ œ

    ์ •๋ ฌ

    • Arrays.sort() -> Dual-Pivot QuickSort ํ˜น์€ Tim-Sort : ์„ฑ๋Šฅ์ข‹์œผ๋‹ˆ๊นŒ ๊ทธ๋ƒฅ ์“ฐ์ž
    // bubble sort ์˜ˆ
    private static int[] bubbleSort(int[] org) {
        int[] arr = org.clone();
        int n = arr.length;
        for(int i=0; i< n; i++) {
            for(int j=0; j<n-i-1; j++) {
                if(arr[j] > arr[j+1]) {
                    int temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                }
            }
        }
    }
    
    • ์›๋ณธ์„ ๊ทธ๋Œ€๋กœ ๋‘๊ณ  ์‹ถ์œผ๋ฉด
    int[] clone = arr.clone();
    

    ๋ฐฐ์—ด ์ œ์–ดํ•˜๊ธฐ

    • ์ค‘๋ณต ์ œ๊ฑฐ
    Integer[] result = Arrays.stream(arr).boxed().distinct().toArray(Integer[]::new);
    
    Arrays.sort(result, Collections.reverseOrder()); 
    
    Arrays.stream(result).mapToInt(Integer::intValue).toArray(); // int[]๋กœ
    
    • ๊ฐ€๊ธ‰์  ํ‘œ์ค€ API๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์‹œ๊ฐ„์ดˆ๊ณผ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก
    TreeSet<Integer> set = new TreeSet<>(Collections.reverseOrder());
    int[] result = new int[set.size()];
    for(int i = 0; i < result.length; i++) {
        result[i] = set.pollFirst();
    } 
    // ์ค‘๋ณต์ œ๊ฑฐ O(N), ์ •๋ ฌ O(NlogN) => O(NlogN)
    
    Created Tue, 22 Apr 2025 20:48:45 +0900