[LG CNS AM CAMP 1기] 백엔드 I 6 | Java

letthem·1일 전
0

LG CNS AM CAMP 1기

목록 보기
16/16
post-thumbnail

함수형 인터페이스에서 제공하는 메서드

andThen(), compose()

함수형 인터페이스를 이어주는 것
andThen() : 왼쪽 -> 오른쪽,
compose() : 오른쪽 -> 왼쪽

인터페이스AB = 인터페이스A.andThen(인터페이스B);
최종결과 = 인터페이스AB.method();
인터페이스AB = 인터페이스A.compose(인터페이스B);
최종결과 = 인터페이스AB.method();

andThen()

package com.test;

import java.util.function.Consumer;

class Member {
private String name;
private String id;
private Address address;

public Member(String name, String id, Address address) {
    this.name = name;
    this.id = id;
    this.address = address;
}

public String getName() {
    return name;
}

public String getId() {
    return id;
}

public Address getAddress() {
    return address;
}

}
class Address {
private String country;
private String city;

public Address(String country, String city) {
    this.country = country;
    this.city = city;
}

public String getCountry() {
    return country;
}

public String getCity() {
    return city;
}

}
public class MyTest {
public static void main(String[] args) {
Consumer memberNameConsumer = m -> System.out.println("memberNameConsumer: " + m.getName());
Consumer memberIdConsumer = m -> System.out.println("memberIdConsumer: " + m.getId());

    Consumer<Member> memberNameIdConsumer = memberNameConsumer.andThen(memberIdConsumer);
    memberNameIdConsumer.accept(new Member("홍길동", "HGD", null));

    Consumer<Member> memberIdNameConsumer = memberIdConsumer.andThen(memberNameConsumer);
    memberIdNameConsumer.accept(new Member("홍길동", "HGD", null));
}

}

![](https://velog.velcdn.com/images/letthem/post/ff59f75a-51e7-4c52-96ca-4a11dbf0127a/image.png)


#### compose()
```java
package com.test;

import java.util.function.Consumer;
import java.util.function.Function;

class Member {
    private String name;
    private String id;
    private Address address;

    public Member(String name, String id, Address address) {
        this.name = name;
        this.id = id;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public String getId() {
        return id;
    }

    public Address getAddress() {
        return address;
    }
}
class Address {
    private String country;
    private String city;

    public Address(String country, String city) {
        this.country = country;
        this.city = city;
    }

    public String getCountry() {
        return country;
    }

    public String getCity() {
        return city;
    }
}

public class MyTest {
    public static void main(String[] args) {
        Function<Member, Address> getAddressFromMember = m -> m.getAddress();
        Function<Address,String> getCityFromAddress = a -> a.getCity();

        Function<Member, String> getCityFromMember;
        String city;

        getCityFromMember = getAddressFromMember.andThen(getCityFromAddress);
        city = getCityFromMember.apply(new Member("홍길동", "HGD", new Address("한국", "서울")));
        System.out.println(city);

        getCityFromMember = getCityFromAddress.compose(getAddressFromMember);
        city = getCityFromMember.apply(new Member("홍길동", "HGD", new Address("한국", "서울")));
        System.out.println(city);
    }
}

and(), or(), negate(), isEqual()

and(), or(), negate()

package com.test;

import java.util.function.IntPredicate;


public class MyTest {
    public static void main(String[] args) {
        IntPredicate predicate2x = n -> n % 2 == 0;
        IntPredicate predicate3x = n -> n % 3 == 0;

        IntPredicate predicate;
        boolean result;

        predicate = predicate2x.and(predicate3x);
        result = predicate.test(9);
        System.out.println("숫자 9는 2와 3의 배수입니까? " + result);

        predicate = predicate2x.or(predicate3x);
        result = predicate.test(9);
        System.out.println("숫자 9는 2 또는 3의 배수입니까? " + result);

        predicate = predicate2x.negate();
        result = predicate.test(9);
        System.out.println("숫자 9는 2의 배수가 아닙니까? " + result);
    }
}

isEqual()

package com.test;

import java.util.function.IntPredicate;
import java.util.function.Predicate;


public class MyTest {
    public static void main(String[] args) {
        Predicate<String> predicate;
        boolean result;

        predicate = Predicate.isEqual(null);
        result = predicate.test(null);
        System.out.println("null == null : " + result);

        predicate = Predicate.isEqual("Java");
        result = predicate.test(null);
        System.out.println("Java == null : " + result);

        predicate = Predicate.isEqual(null);
        result = predicate.test("Java");
        System.out.println("null == Java : " + result);

        predicate = Predicate.isEqual("Java");
        result = predicate.test("Java");
        System.out.println("Java == Java : " + result);
    }
}

string이 아닌 객체가 들어올 때 쓸 수 있을듯,, 근데 별로 쓸 일 없을 것 같다.

minBy(), maxBy()

BinaryOperator<T> 함수형 인터페이스에서 제공하는 정적 메서드로,
매개변수로 Comparator<T> 함수형 인터페이스를 제공

package com.test;

import java.util.function.BinaryOperator;
import java.util.function.IntPredicate;
import java.util.function.Predicate;

class Fruit {
    private String name;
    private int price;

    public Fruit(String name, int price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return this.name;
    }

    public int getPrice() {
        return this.price;
    }
}

public class MyTest {
    public static void main(String[] args) {
        BinaryOperator<Fruit> bio;
        Fruit fruit;

        bio = BinaryOperator.minBy((f1, f2) -> Integer.compare(f1.getPrice(), f2.getPrice()));
        fruit = bio.apply(new Fruit("딸기", 12000), new Fruit("사과", 9000));
        System.out.println(fruit.getName());

        bio = BinaryOperator.maxBy((f1, f2) -> Integer.compare(f1.getPrice(), f2.getPrice()));
        fruit = bio.apply(new Fruit("딸기", 12000), new Fruit("사과", 9000));
        System.out.println(fruit.getName());
    }
}

스트림(Stream) ⭐️⭐️⭐️

자바8에서 추가된 컬렉션(배열 포함)의 저장 요소를 하나씩 참조해서 람다식으로 처리할 수 있도록 해 주는 반복자

함수형 인터페이스를 이용해서 선언하는 형태로 코드를 만들 수 있다!!!
=> 람다식이나 메서드 참조형 사용할 수 있다 !

람다식과 짝꿍 🩷

import org.w3c.dom.ls.LSOutput;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Stream;

public class Example {
    public static void main(String[] args) {
        List<String> lists = Arrays.asList("aaa", "bbb", "ccc");

        // Iterator
        Iterator<String> it = lists.iterator();
        while (it.hasNext()) {
            String item = it.next();
            System.out.println(item);
        }

        // Stream
        Stream<String> st = lists.stream();
        st.forEach(item -> System.out.println(item));

        st = lists.stream();
        st.forEach(System.out::println);

    }
}

람다식 또는 메서드 참조로 요소 처리 코드를 제공한다.

이것만 잘하면 됨 !!!!! ⭐️⭐️⭐️⭐️⭐️ ⬇️

lists.stream().map(String::toUpperCase).forEach(System.out::println);

리스트를 stream (돌면서) 대문자로 map(바꾸고) forEach(돌면서 각각) 출력하기

활용 예시 ⬇️

import lombok.*;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

@Getter
@AllArgsConstructor
class Student {
    String name;
    int Score;
}

public class Example {
    public static void main(String[] args) {
        List<Student> students = Arrays.asList(
                new Student("홍길동", 90), new Student("고길동", 80),
                new Student("임길동", 90), new Student("이길동", 80),
                new Student("삼길동", 90), new Student("사길동", 80));

        Stream<Student> stream = students.stream();
        stream.forEach(s -> System.out.printf("%s : %d\n", s.getName(), s.getScore()));

        // forEach() : List 인터페이스의 default 메서드 -> Stream 없이도 리스트 요소를 반복 처리 가능
        students.forEach(s -> System.out.printf("%s : %d\n", s.getName(), s.getScore()));
    }
}
import lombok.*;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

@Getter
@AllArgsConstructor
class Student {
    String name;
    int Score;
}

public class Example {
    public static void print(Student s) {
        System.out.printf("[%s] %s : %d\n", Thread.currentThread().getName(), s.getName(), s.getScore());
    }

    public static void main(String[] args) {
        List<Student> students = Arrays.asList(
                new Student("홍길동", 90), new Student("고길동", 80),
                new Student("임길동", 90), new Student("이길동", 80),
                new Student("삼길동", 90), new Student("사길동", 80));

        // 순차 처리
        Stream<Student> stream = students.stream();
        stream.forEach(Example::print);

        System.out.println();

        // 병렬 처리
        Stream<Student> parallelStream = students.parallelStream();
        parallelStream.forEach(Example::print);
    }
}

Thread, Stream
대용량 데이터를 처리할 때 병렬 처리로 하면 효율적이다.
worker 들이 같이 처리해준다!!

Stream을 사용하면 데이터를 원하는 대로 가공하고 결과물을 뽑아낼 수 있다.

import lombok.*;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

@Getter
@AllArgsConstructor
class Student {
    String name;
    int Score;
}

public class Example {
    public static void print(Student s) {
        System.out.printf("[%s] %s : %d\n", Thread.currentThread().getName(), s.getName(), s.getScore());
    }

    public static void main(String[] args) {
        List<Student> students = Arrays.asList(
                new Student("홍길동", 90), new Student("고길동", 80),
                new Student("임길동", 90), new Student("이길동", 80),
                new Student("삼길동", 90), new Student("사길동", 80));

        double average = students.stream()
                .mapToInt(Student::getScore) // 학생의 점수를 맵핑
                .average()
                .getAsDouble();

        System.out.println(average);
    }
}


import lombok.*;

import java.util.Arrays;
import java.util.stream.IntStream;
import java.util.stream.Stream;


public class Example {
    public static void main(String[] args) {
        String[] strArr = { "홍길동", "고길동", "신길동" };

        Stream<String> strStm = Arrays.stream(strArr);
        strStm.forEach(s -> System.out.println(s));

        strStm = Arrays.stream(strArr);
        strStm.forEach(System.out::println);

        int[] intArr = { 10, 20, 30 };
        IntStream intStm = Arrays.stream(intArr);
        intStm.forEach(s -> System.out.println(s));
    }
}

1부터 100까지 더하기 & 1부터 99까지 더하기 ⬇️

import java.util.stream.IntStream;

public class Example {
    public static int sum = 0;

    public static void main(String[] args) {
        IntStream stream = IntStream.rangeClosed(1, 100); // 1 ~ 100까지 추출
        stream.forEach(n -> sum += n);
        System.out.println(sum); // 5050

        sum = 0;
        IntStream stream2 = IntStream.range(1, 100); // 1 ~ 99까지 추출
        stream2.forEach(n -> sum += n);
        System.out.println(sum); // 4950
    }
}

평균 나이 계산 ⬇️

import lombok.*;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

import static java.util.Locale.filter;

@AllArgsConstructor
@Getter
class Member {
    public static int MALE = 0;
    public static int FEMALE = 1;

    private String name;
    private int gender;
    private int age;
}

public class Example {
    public static void main(String[] args) throws IOException {
        List<Member> members = Arrays.asList(
                new Member("홍길동", Member.MALE, 30),
                new Member("고길동", Member.MALE, 40),
                new Member("이하니", Member.FEMALE, 20),
                new Member("삼하니", Member.FEMALE, 30));

        double maleAvgAge = members.stream()
                .filter(m -> m.getGender() == Member.MALE)
                // .mapToInt(m -> m.getAge())
                .mapToInt(Member::getAge)
                .average()
                .getAsDouble();
        System.out.println("남자 평균 나이 : " + maleAvgAge);
    }
}

distinct() : 중복 없이 나오는 것

filter() : 조건에 맞는 것만 나오는 것

import lombok.*;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

import static java.util.Locale.filter;

public class Example {
    public static void main(String[] args) throws IOException {
        List<String> stations = Arrays.asList("부평시장", "홍대입구", "강남", "신도림", "역삼", "삼성", "신림", "부평구청", "신도림");

        stations.stream()
                .distinct()
                .forEach(System.out::println);

        System.out.println();

        stations.stream()
                .filter(s -> s.startsWith("신"))
                .forEach(System.out::println);

        System.out.println();

        stations.stream()
                .filter(s -> s.startsWith("신"))
                .distinct()
                .forEach(System.out::println);

    }
}

map() : n : n 으로 새롭게 만들어진다.


flatMapXXX() 메서드

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

public class Example {
    public static void main(String[] args) throws IOException {
        List<String> list1 = Arrays.asList("java8 lambda", "stream mapping api");
        list1.stream()
                .flatMap(d -> Arrays.stream(d.split(" ")))
                .forEach(System.out::println);
    }
}

배열을 stream으로 바꾼다.
flatMap() : 데이터의 개수가 바뀔 수 있다. 기준에 맞춰(여기선 공백으로 자르기) 스트림으로 만들어주는 것

flatMapXXX()
flatMapToInt() ⬇️

import lombok.*;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

public class Example {
    public static void main(String[] args) throws IOException {

        List<String> list2 = Arrays.asList("10, 20, 30, 40, 50, 60");
        list2.stream()
                .flatMapToInt(d -> {
                    String[] strArray = d.split(",");
                    int[] intArray = new int[strArray.length];
                    for (int i = 0; i < strArray.length; i++) {
                        intArray[i] = Integer.parseInt(strArray[i].trim());
                    }
                    return Arrays.stream(intArray);
                })
                .forEach(System.out::println);
    }
}
import lombok.*;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

@Getter
@AllArgsConstructor
class Student {
    String name;
    int score;
}

public class Example {
    public static void main(String[] args) throws IOException {
        List<Student> students = Arrays.asList(
                new Student("홍길동", 90), new Student("고길동", 80),
                new Student("일길동", 90), new Student("이길동", 80),
                new Student("삼길동", 90), new Student("사길동", 80));
        students.stream()
                .mapToInt(Student::getScore)
                .forEach(System.out::println);
    }
}

온라인 도서 관리 시스템 (CRUD) ⭐️🩷⭐️🩷⭐️🩷⭐️🩷⭐️🩷⭐️🩷⭐️🩷

컬렉션 프레임워크 + 함수형 프로그래밍을 사용해서 만들어보자 !
도서 등록, 전체 조회, 검색, 삭제, 인기 도서 검색 등의 기능을 제공
도서정보 : ISBN, 제목, 저자, 출판연도

Book.java

(Entity)

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;

@AllArgsConstructor
@Getter
@ToString
public class Book {
    private String isbn;
    private String title;
    private String author;
    private int year;
}

LibraryManagement.java ⭐️🩷⭐️🩷⭐️🩷⭐️🩷⭐️🩷⭐️🩷⭐️🩷⭐️🩷

(Service)

기능

  • 도서 등록
  • 전체 도서 목록 조회
  • 도서 검색 => 책이름과 저자 항목에 keyword가 포함되어 있는지 검색
  • 도서 삭제
  • 인기 도서 조회
import java.util.*;

public class LibraryManagement {
    // 변수들 ⬇️
    // 도서 정보
    private List<Book> books = new ArrayList<>();

    // ISBN => 도서 등록 시 동일 도서가 존재하는지 확인
    private Set<String> isbnSet = new HashSet<>();

    // 조회수 => ISBN, 조회수 정보를 관리
    private Map<String, Integer> bookViews = new HashMap<>();

    // 기능 함수들 ⬇️
    // 도서 등록
    public void addBook(Book book) {
        if (isbnSet.contains(book.getIsbn())) {
            System.out.printf("ISBN %s과 동일한 도서가 이미 등록되어 있습니다.\n", book.getIsbn());
            return;
        }

        books.add(book);
        isbnSet.add(book.getIsbn());
        bookViews.put(book.getIsbn(), 0);
        System.out.println("정상적으로 등록되었습니다." + book);
    }

    // 전체 도서 목록 조회
    public void listBooks() {
        if (books.isEmpty()) {
            System.out.println("등록된 도서가 없습니다.");
            return;
        }

        books.forEach(System.out::println);
    }
    
    // 도서 검색 => 책이름과 저자 항목에 keyword가 포함되어 있는지 검색
    public void searchBooks(String keyword) {
        keyword = keyword.trim().toLowerCase();

        boolean found = false;
        for (Book book : books) {
            if (book.getTitle().trim().toLowerCase().contains(keyword) ||
                    book.getAuthor().trim().toLowerCase().contains(keyword)) {
                System.out.println(book);
                bookViews.put(book.getIsbn(), bookViews.get(book.getIsbn()) + 1);
                found = true;
            }
        }

        if (!found) {
            System.out.printf("%s를 포함하는 도서가 없습니다.\n", keyword);
        }
    }

    // 도서 삭제
    public void deleteBook(String isbn) {
        Iterator<Book> iterator = books.iterator();
        while (iterator.hasNext()) {
            Book book = iterator.next();
            if (book.getIsbn().equals(isbn)) {
                iterator.remove();
                isbnSet.remove(isbn);
                bookViews.remove(isbn);
                System.out.printf("ISBN %s 책을 삭제했습니다.\n", isbn);
                return;
            }
        }

        System.out.printf("ISBN %s와 일치하는 도서를 찾을 수 없습니다.\n", isbn);
    }
    
    // 인기 도서 조회
    public void mostViewedBooks() {
        int maxViews = Collections.max(bookViews.values());

        if (bookViews.isEmpty() || maxViews == 0) {
            System.out.println("등록된 인기 도서가 없습니다.");
            return;
        }

        for (Map.Entry<String, Integer> entry : bookViews.entrySet()) {
            if (entry.getValue() == maxViews) {
                books.stream()
                        .filter(book -> book.getIsbn().equals(entry.getKey()))
                        .forEach(System.out::println);
            }
        }

    }
}

Main.java

(실행)

public class Main {
    public static void main(String[] args) {
        LibraryManagement library = new LibraryManagement();

        Book book1 = new Book("12345", "Java Programming", "John", 2020);
        Book book2 = new Book("67890", "Python Programming", "Jom", 2024);
        Book book3 = new Book("88888", "C++ Programming", "Jane", 2000);

        library.listBooks(); // 등록된 도서가 없습니다.

        library.addBook(book1);
        library.addBook(book1); // ISBN 12345과 동일한 도서가 이미 등록되어 있습니다.
        library.addBook(book2);
        library.addBook(book3);

        library.listBooks();

        System.out.println(">>>>");
        library.mostViewedBooks(); // 등록된 인기 도서가 없습니다.

        library.searchBooks("programming");
        library.searchBooks("Java");
        library.searchBooks("Mybook"); // mybook를 포함하는 도서가 없습니다.

        System.out.println(">>>>");
        library.mostViewedBooks();

        library.deleteBook("99999"); // ISBN 99999와 일치하는 도서를 찾을 수 없습니다.
        library.deleteBook("88888"); // ISBN 88888 책을 삭제했습니다.

        library.listBooks();

    }
}

input을 받으며 동작하게 바꾸기!

LibraryManagement.java

import java.util.*;

public class LibraryManagement {
    // 도서 정보
    private List<Book> books = new ArrayList<>();

    // ISBN => 도서 등록 시 동일 도서가 존재하는지 확인
    private Set<String> isbnSet = new HashSet<>();

    // 조회수 => ISBN, 조회수 정보를 관리
    private Map<String, Integer> bookViews = new HashMap<>();

    // 도서 등록
    public void addBook(Scanner scanner) {
        System.out.print("ISBN: ");
        String isbn = scanner.nextLine();

        if (isbnSet.contains(isbn)) {
            System.out.printf("ISBN %s과 동일한 도서가 이미 등록되어 있습니다.\n", isbn);
            return;
        }

        System.out.print("제목: ");
        String title = scanner.nextLine();

        System.out.print("저자: ");
        String author = scanner.nextLine();

        System.out.print("년도: ");
        int year = scanner.nextInt();
        scanner.nextLine();

        Book book = new Book(isbn, title, author, year);
        books.add(book);
        isbnSet.add(book.getIsbn());
        bookViews.put(book.getIsbn(), 0);
        System.out.println("정상적으로 등록되었습니다." + book);
    }

    // 전체 도서 목록 조회
    public void listBooks() {
        if (books.isEmpty()) {
            System.out.println("등록된 도서가 없습니다.");
            return;
        }

        books.forEach(System.out::println);
    }

    // 도서 검색 => 책이름과 저자 항목에 keyword가 포함되어 있는지 검색
    public void searchBooks(Scanner scanner) {
        System.out.print("검색어를 입력하세요: ");
        String keyword = scanner.nextLine();
        keyword = keyword.trim().toLowerCase();

        boolean found = false;
        for (Book book : books) {
            if (book.getTitle().trim().toLowerCase().contains(keyword) ||
                    book.getAuthor().trim().toLowerCase().contains(keyword)) {
                System.out.println(book);
                bookViews.put(book.getIsbn(), bookViews.get(book.getIsbn()) + 1);
                found = true;
            }
        }

        if (!found) {
            System.out.printf("%s를 포함하는 도서가 없습니다.\n", keyword);
        }
    }

    // 도서 삭제
    public void deleteBook(Scanner scanner) {
        System.out.print("삭제할 도서의 ISBN을 입력하세요: ");
        String isbn = scanner.nextLine();

        Iterator<Book> iterator = books.iterator();
        while (iterator.hasNext()) {
            Book book = iterator.next();
            if (book.getIsbn().equals(isbn)) {
                iterator.remove();
                isbnSet.remove(isbn);
                bookViews.remove(isbn);
                System.out.printf("ISBN %s 책을 삭제했습니다.\n", isbn);
                return;
            }
        }

        System.out.printf("ISBN %s와 일치하는 도서를 찾을 수 없습니다.\n", isbn);
    }

    // 인기 도서 조회
    public void mostViewedBooks() {
        int maxViews = Collections.max(bookViews.values());

        if (bookViews.isEmpty() || maxViews == 0) {
            System.out.println("등록된 인기 도서가 없습니다.");
            return;
        }

        for (Map.Entry<String, Integer> entry : bookViews.entrySet()) {
            if (entry.getValue() == maxViews) {
                books.stream()
                        .filter(book -> book.getIsbn().equals(entry.getKey()))
                        .forEach(System.out::println);
            }
        }
    }

}

Main.java

import java.util.Scanner;

public class Main {

    public static void printMenu() {
        System.out.println("\n도서 관리: ");
        System.out.println("1. 도서 등록");
        System.out.println("2. 전체 도서 출력");
        System.out.println("3. 도서 검색");
        System.out.println("4. 도서 삭제");
        System.out.println("5. 인기 도서 조회");
        System.out.println("6. 종료");
        System.out.print("메뉴를 선택하세요: ");
    }

    public static void main(String[] args) {
        LibraryManagement library = new LibraryManagement();
        Scanner scanner = new Scanner(System.in);

        while(true) {
            printMenu();

            int choice = scanner.nextInt();
            scanner.nextLine();

            switch(choice) {
                case 1:
                    library.addBook(scanner);
                    break;
                case 2:
                    library.listBooks();
                    break;
                case 3:
                    library.searchBooks(scanner);
                    break;
                case 4:
                    library.deleteBook(scanner);
                    break;
                case 5:
                    library.mostViewedBooks();
                    break;
                case 6:
                    System.out.println("프로그램을 종료합니다.");
                    scanner.close();
                    return;
                default:
                    System.out.println("잘못된 입력입니다.");
            }
        }

    }

}

미니 프로젝트 (1/17 13시까지)

개인별로 데이터를 관리하는 CLI 기반의 애플리케이션을 작성하고, 조별로 통합해서 제공

내가 만든 Diary 클래스 !!

Diary 만들었다 ㅎㅎ 귀욥게 ,,

import java.util.*;
import java.util.stream.Collectors;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;

@AllArgsConstructor
@Getter
@ToString
class Diary {
    private Long id;
    private String title;
    private int weather;
    private int mood;
    private String contents;

    // Weather와 Mood 이모지 매핑
    private static final Map<Integer, String> WEATHER_EMOJIS = Map.of(
            1, "☀️",
            2, "🌥️",
            3, "☁️️",
            4, "☔️",
            5, "☃️"
    );

    private static final Map<Integer, String> MOOD_EMOJIS = Map.of(
            1, "😡",
            2, "😭",
            3, "🧐",
            4, "😊",
            5, "😍"
    );

    // 이모지 반환 메서드
    public String getWeatherEmoji() {
        return WEATHER_EMOJIS.getOrDefault(weather, "❓");
    }

    public String getMoodEmoji() {
        return MOOD_EMOJIS.getOrDefault(mood, "❓");
    }

    // 특정 weather와 mood에 대한 이모지 반환
    public static String getWeatherEmojiByValue(int weather) {
        return WEATHER_EMOJIS.getOrDefault(weather, "❓");
    }

    public static String getMoodEmojiByValue(int mood) {
        return MOOD_EMOJIS.getOrDefault(mood, "❓");
    }

    @Override
    public String toString() {
        return String.format(
                "===========================\n" +
                        "📓 %d번째 일기\n" +
                        "📝 제목: %s\n" +
                        "🌤️ 날씨: %s\n" +
                        "😊 기분: %s\n" +
                        "🖋️ 내용: %s\n" +
                        "===========================",
                id, title, getWeatherEmoji(), getMoodEmoji(), contents
        );
    }
}

class DiaryManagement {
    // 일기 정보
    private final List<Diary> diaries = new ArrayList<>();

    // 조회수 => ID, 조회수 정보를 관리
    private final Map<Long, Integer> diaryViews = new HashMap<>();

    private long nextId = 1;

    // 도서 등록
    public void addDiary(Scanner scanner) {
        Long id = nextId++;

        System.out.print("제목을 알려주세요 ✨ ");
        String title = scanner.nextLine();

        int weather = 0;
        while (true) {
            try {
                System.out.print("오늘 날씨는 어땠나요? 1 ~ 5 중에서 입력해주세요! (1: ☀️, 2: 🌥️, 3: ☁️️, 4: ☔️, 5: ☃️) ");
                weather = Integer.parseInt(scanner.nextLine().trim());
                if (weather < 1 || weather > 5) {
                    throw new IllegalArgumentException("1부터 5 사이의 숫자를 입력해주세요.");
                }
                break;
            } catch (NumberFormatException e) {
                System.out.println("숫자를 입력해주세요!");
            } catch (IllegalArgumentException e) {
                System.out.println(e.getMessage());
            }
        }

        int mood = 0;
        while (true) {
            try {
                System.out.print("오늘의 기분을 1 ~ 5 중에서 입력해주세요! (1: 😡, 2: 😭, 3: 🧐, 4: 😊, 5: 😍) ");
                mood = Integer.parseInt(scanner.nextLine().trim());
                if (mood < 1 || mood > 5) {
                    throw new IllegalArgumentException("1부터 5 사이의 숫자를 입력해주세요.");
                }
                break;
            } catch (NumberFormatException e) {
                System.out.println("숫자를 입력해주세요!");
            } catch (IllegalArgumentException e) {
                System.out.println(e.getMessage());
            }
        }

        System.out.print("내용을 채워주세요 🍀 ");
        String contents = scanner.nextLine();

        Diary diary = new Diary(id, title, weather, mood, contents);
        diaries.add(diary);
        diaryViews.put(diary.getId(), 0);
        System.out.println("\n\n\n오늘의 일기 ʕ•ᴥ•ʔ\n" + diary);
    }

    // 전체 일기 목록 조회
    public void listDiaries() {
        if (diaries.isEmpty()) {
            System.out.println("\n등록된 일기가 없습니다.");
            return;
        }

        diaries.forEach(System.out::println);
    }

    // 일기 검색 => 일기 제목과 내용에 keyword가 포함되어 있는지 검색
    public void searchDiaries(Scanner scanner) {
        System.out.print("제목이나 내용을 입력하세요: ");
        String keyword = scanner.nextLine();
        keyword = keyword.trim().toLowerCase();

        boolean found = false;
        for (Diary diary : diaries) {
            if (diary.getTitle().trim().toLowerCase().contains(keyword) ||
                    diary.getContents().trim().toLowerCase().contains(keyword)) {
                System.out.println(diary);
                diaryViews.put(diary.getId(), diaryViews.get(diary.getId()) + 1);
                found = true;
            }
        }

        if (!found) {
            System.out.printf("\n%s을(를) 포함하는 일기가 없습니다.\n", keyword);
        }
    }

    // weather로 일기 검색
    public void searchDiariesByWeather(Scanner scanner) {
        int weather = 0;

        // 잘못된 입력에 대한 반복 처리
        while (true) {
            try {
                System.out.print("검색할 날씨를 1 ~ 5 중에서 입력해주세요! (1: ☀️, 2: 🌥️, 3: ☁️️, 4: ☔️, 5: ☃️) ");
                weather = Integer.parseInt(scanner.nextLine().trim());
                if (weather < 1 || weather > 5) {
                    throw new IllegalArgumentException("1부터 5 사이의 숫자를 입력해주세요.");
                }
                break;
            } catch (NumberFormatException e) {
                System.out.println("숫자를 입력해주세요!");
            } catch (IllegalArgumentException e) {
                System.out.println(e.getMessage());
            }
        }

        // weather 값에 해당하는 이모지 가져오기
        String weatherEmoji = Diary.getWeatherEmojiByValue(weather);

        // weather 값 필터링
        int finalWeather = weather;
        List<Diary> filteredDiaries = diaries.stream()
                .filter(diary -> diary.getWeather() == finalWeather)
                .collect(Collectors.toList());

        if (filteredDiaries.isEmpty()) {
            System.out.printf("\n%s 날씨에 해당하는 일기가 없습니다.\n", weatherEmoji);
            return;
        }

        System.out.printf("\n%s 날씨에 해당하는 일기 목록입니다 ⭐️📎\n", weatherEmoji);
        filteredDiaries.forEach(System.out::println);
    }

    // mood로 일기 검색
    public void searchDiariesByMood(Scanner scanner) {
        int mood = 0;

        // 잘못된 입력에 대한 반복 처리
        while (true) {
            try {
                System.out.print("검색할 기분을 1 ~ 5 중에서 입력해주세요! (1: 😡, 2: 😭, 3: 🧐, 4: 😊, 5: 😍) ");
                mood = Integer.parseInt(scanner.nextLine().trim());
                if (mood < 1 || mood > 5) {
                    throw new IllegalArgumentException("1부터 5 사이의 숫자를 입력해주세요.");
                }
                break;
            } catch (NumberFormatException e) {
                System.out.println("숫자를 입력해주세요!");
            } catch (IllegalArgumentException e) {
                System.out.println(e.getMessage());
            }
        }

        // mood 값에 해당하는 이모지 가져오기
        String moodEmoji = Diary.getMoodEmojiByValue(mood);

        // mood 값 필터링
        int finalMood = mood;
        List<Diary> filteredDiaries = diaries.stream()
                        .filter(diary -> diary.getMood() == finalMood)
                        .collect(Collectors.toList());

        if (filteredDiaries.isEmpty()) {
            System.out.printf("\n%s 기분에 해당하는 일기가 없습니다.\n", moodEmoji);
            return;
        }

        System.out.printf("\n%s 기분에 해당하는 일기 목록입니다 ⭐️📎\n", moodEmoji);
        filteredDiaries.forEach(System.out::println);
    }

    // 일기 삭제
    public void deleteDiary(Scanner scanner) {
        System.out.print("\n삭제할 일기의 번호를 입력하세요: ");
        Long id = Long.valueOf(scanner.nextLine());

        Iterator<Diary> iterator = diaries.iterator();
        while (iterator.hasNext()) {
            Diary diary = iterator.next();
            if (diary.getId().equals(id)) {
                iterator.remove();
                diaryViews.remove(id);
                System.out.printf("\n%s번째 일기를 삭제했습니다.\n", id);
                return;
            }
        }

        System.out.printf("\n%s번째 일기를 찾을 수 없습니다.\n", id);
    }

    // 조회수가 높은 일기 조회
    public void mostViewedDiaries() {
        if (diaryViews.isEmpty()) {
            System.out.println("\n등록된 일기가 없습니다.");
            return;
        }

        // 조회수가 가장 높은 값 구하기
        int maxViews = diaryViews.values().stream()
                .max(Integer::compareTo)
                .orElse(0);

        if (maxViews == 0) {
            System.out.println("\n조회수가 높은 일기가 없습니다.");
            return;
        }

        // 조회수가 가장 높은 일기를 필터링
        System.out.println("\n조회수가 가장 높은 일기 목록입니다 🩷️📎\n");
        diaries.stream()
                .filter(diary -> diaryViews.get(diary.getId()) == maxViews)
                .forEach(System.out::println);
    }


}


public class Suyeon {

    public void printMenu() {
        System.out.println("\n🩷🔑♥*♡+:。.。.。:+♡*♥ My Diary ♥*♡+:。.。.。:+♡*♥📎📔\n");
        System.out.println("1. 일기를 작성해 보아요 ✏️");
        System.out.println("2. 모든 일기를 보고싶다면 👀");
        System.out.println("3. 제목과 내용으로 검색해 보아요 📝🔎");
        System.out.println("4. 날씨로 검색해 보아요 🌈🔎");
        System.out.println("5. 기분으로 검색해 보아요 😃🔎");
        System.out.println("6. 지우고 싶은 일기가 있어요 🗑️");
        System.out.println("7. 어떤 일기를 가장 많이 봤을까? 🧐❓");
        System.out.println("8. 일기장 오늘은 이만 덮을게요. 다음에 또 봐요 !! 👋🌌");
        System.out.print("\n원하시는 메뉴를 숫자로 입력해 주세요 🪄✨ ");
    }

    public void diaryApp(Scanner scanner) {
        DiaryManagement bookcase = new DiaryManagement();

        while(true) {
            printMenu();

            try {
                int choice = Integer.parseInt(scanner.nextLine().trim());

                switch(choice) {
                case 1:
                    bookcase.addDiary(scanner);
                    break;
                case 2:
                    bookcase.listDiaries();
                    break;
                case 3:
                    bookcase.searchDiaries(scanner);
                    break;
                case 4:
                    bookcase.searchDiariesByWeather(scanner);
                    break;
                case 5:
                    bookcase.searchDiariesByMood(scanner);
                    break;
                case 6:
                    bookcase.deleteDiary(scanner);
                    break;
                case 7:
                    bookcase.mostViewedDiaries();
                    break;
                case 8:
                    System.out.println("\n\n\nGood Bye 。.. 💌 .°⑅ପ₍ᐢ。•༝•。ᐢ₎ଓ⑅°.");
                    return;
                default:
                    System.out.println("\n\n\n1 ~ 8 중에서 입력해주세요! .°⑅ପ₍ᐢ。•༝•。ᐢ₎ଓ⑅°.");
                }
            } catch (NumberFormatException e) {
                System.out.println("\n\n\n숫자를 입력해주세요! .°⑅ପ₍ᐢ。•༝•。ᐢ₎ଓ⑅°.");
            }
        }
    }
}


난 자바도 프론트처럼 해 ,,,, .°⑅ପ₍ᐢ。•༝•。ᐢ₎ଓ⑅°.

0개의 댓글