본문 바로가기
네이버클라우드/JAVA 웹 프로그래밍

JAVA 20일차 (2023-06-20) 자바 기초 DAY18_Stack, Queue 자료구조 구현_개인프로젝트 - 마트 관리 시스템

by prometedor 2023. 6. 20.
## 22. Stack, Queue 자료구조 구현하기

- Stack과 Queue의 구동원리 이해 및 구현
- Stack 적용
  - Prompt 클래스의 서브 클래스 MenuPrompt 정의
  - MenuPrompt에서 Stack을 이용하여 프롬프트 제목에 breadcrumb 기능을 적용
- Queue 적용
  - MenuPrompt 클래스에 메뉴 출력 기능을 추가
    - App, BoardHandler, MemberHandler 변경
  - MenuPrompt 클래스에 입력한 명령어의 history 기능을 추가

 

 

Stack과 Queue의 구동원리 이해 및 구현

ㄴ Stack 클래스 생성

 

Stack.java

ㄴ push => 목록 맨 끝에 추가하는 것

ㄴ LinkedList(상속 받은 메서드 = 서브 클래스에서 사용할 수 있는 수퍼 클래스)에 있는 add 를 이용하여 기능을 구현

 

ㄴ Member와 Student 클래스 생성하여 테스트

 

Member.java

ㄴ Member 클래스 작성

 

Student.java

ㄴ Member 클래스를 상속 받는 Student 클래스 작성

 

 

ㄴ 자바의 최상위 클래스인 Object 클래스에는 필드가 없음을 우측의 outline 을 통해 알 수 있음

 

ㄴ 해당 경로에 src.zip 파일이 위치함

=>

ㄴ src.zip 파일이 있음을 확인

=> src.zip 파일은 Java 개발 키트 (JDK) 라이브러리의 소스 코드를 포함하고 있으며, 일반적으로 JDK 설치와 함께 제공됨

=> 이 파일은 표준 Java 클래스와 라이브러리의 소스 코드에 대한 접근을 제공하여 개발자가 다양한 Java API의 구현 세부 정보를 살펴볼 수 있게 함

 

 

ㄴ Test 파일 생성

 

Test.java

ㄴ Student 클래스는 Member 클래스를 상속 받았으므로 Member 클래스의 변수도 사용 가능

 

Stack.java

ㄴ  stack 의 크기가 0이면 null 을 리턴

 

Stack.java

ㄴ LinkedList 클래스의 remove(int index) 메서드를 사용

 

Stack.java

ㄴ this.size() 는 스택의 크기이므로 remove(int index) 메서드에는 index 에 해당하는 size() - 1 을 아규먼트로 받도록 함

=> 마지막 요소를 삭제하면서 반환

 

Stack.java

=>

Stack.java

ㄴ deletedValue 는 삭제하려는 요소이고 이름 삭제한 후 리턴

 

Stack.java

=>

ㄴ stack 클래스에서 main 을 생성하여 테스트

 

 

Stack 적용

ㄴ Prompt 클래스의 서브 클래스 MenuPrompt 정의

ㄴ Prompt 클래스의 서브 클래스인 MenuPrompt 를 생성

 

MenuPrompt.java

ㄴ breadcrumbs => "홈 > 카테고리 > 서브카테고리 > 현재페이지 " 와 같이 현재 위치를 시각적으로 표시하는 탐색 요소

 

MenuPrompt.java

ㄴ appendBreadcrumbs 는 title 을 push() 메서드를 이용해 넣고 breadcrumbs 를 pop() 메서드를 이용하여 삭제

 

MenuPrompt.java

=>

MenuPrompt.java

=>

ㄴ breadcrumbs : Stack 자료구조를 이용하여 현재 위치를 나타내는 경로를 저장

     ㄴ 경로의 각 요소는 문자열로 표현됨

     ㄴ appendBreadcrumbs 메소드를 통해 경로를 추가하고, removeBreadcrumbs 메소드를 통해 경로에서 마지막 요소를 제거

ㄴ appendBreadcrumbs(String title): 경로에 새로운 요소를 추가

     ㄴ title은 추가할 경로 요소의 제목

ㄴ removeBreadcrumbs(): 경로에서 마지막 요소를 제거
ㄴ inputMenu(): 현재 위치를 나타내는 경로를 기반으로 메뉴 입력을 받음

 

MenuPrompt.java

ㄴ  경로가 "메인/회원"인 경우 "메인/회원>"을 반환함

 

 

Stack 적용

ㄴ MenuPrompt에서 Stack을 이용하여 프롬프트 제목에 breadcrumb 기능을 적용

 

App.java

ㄴ App 클래스에서 MenuPrompt 를 사용하기 위해 코드 추가

 

App.java

ㄴ MenuPrompt 클래스에 있는 appendBreadcrumbs 메서드에 "메인" 이라는 String 타입의 아규먼트를 전달해줌

 

App.java

ㄴ MenuPrompt 클래스에 있는 inputMenu 메서드를 이용

=> prompt.inputString("메인> "); 코드를 prompt.inputMenu() 로 변경

 

BoardHandler.java

ㄴ BoardHandler.java 에서 MenuPrompt 클래스를 사용하기 위해 코드 추가

 

BoardHandler.java

ㄴ Prompt -> MenuPrompt

 

BoardHandler.java

ㄴ execute() 실행 시 MenuPrompt 의 breadcrumbs 에 현재 메뉴 타이틀을 넣음

 

BoardHandler.java

=>

ㄴ App 클래스에서와 같이 inputString("%s> ", title); 대신 inputMenu() 메서드를 사용

=> ex) 메인/게시글> 

 

BoardHandler.java

ㄴ 0 선택 시 Stack 에 있던 breadcrumbs pop() 되므로 ex) 메인/게시글>   =>   메인>   으로 변경되고 return을 만나 while 문을 나가서 App 클래스의 while 문으로 리턴됨

=> MemberHandler, ItemHandler 클래스도 마찬가지로 수정함

 

 

StringBuilder 사용해보기

MenuPrompt.java

=>

MenuPrompt.java

 

Queue 적용

MenuPrompt 클래스에 메뉴 출력 기능을 추가

ㄴ App, BoardHandler, MemberHandler 변경

ㄴ Queue 클래스 생성

 

Queue.java

ㄴ LinkedList 클래스의 add(value) 메서드를 이용한 offer(Object value) 메서드를 생성

ㄴ LinkedList 의 size() 와 remove(int index) 를 이용한 poll() 메서드를 생성

ㄴ size 가 0이면 null 을 리턴

ㄴ size 가 0보다 크면 해당 index 의 요소를 삭제

 

Queue.java

ㄴ Queue 클래스에 main 을 작성하여 테스트

 

Queue.java

ㄴ breadcrumbs 와 함께 menus 도 같이 받아오기 위해 선언

 

MenuPrompt.java

ㄴ menus 라는 이름으로 새로운 인스턴스를 생성하여 인스턴스명을 이용

ㄴ appendBreadcrumbs(String title, String menu) 메서드는 메뉴 경로와 해당 메뉴를 breadcrumbs 스택과 menus 스택에 추가하는 역할

ㄴ 메뉴 경로는 title 파라미터로 전달되고, 해당 메뉴는 menu 파라미터로 전달됨

ㄴ breadcrumbs.push(title)을 호출하여 메뉴 경로를 breadcrumbs 스택에 추가

ㄴ menus.push(menu)를 호출하여 해당 메뉴를 menus 스택에 추가

=> breadcrumbs 스택에는 이전 메뉴 경로들이 순서대로 쌓이고, menus 스택에는 이전 메뉴들이 순서대로 쌓이게 됨

 

 

MenuPrompt.java

ㄴ printMenu() 라는 메서드를 생성

ㄴ Stack 은 LinkedList 를 상속받았으므로 Stack 으로 인스턴스 변수 생성 시 인스턴스명을 통해 LinkedList 클래스의 get(int index) 메서드를 사용할 수 있음

ㄴ menus.size() 에서 - 1 을 해주는 이유는 index 는 개수보다 1개 작기 때문

 

 

 

 

ㄴ java.base > java.util > Stack 클래스에는 조회만을 위한 peek() 이라는 메소드 가 있음

=> 스택의 맨 위에서부터 하나씩 조회 가능

 

Stack.java

ㄴ Stack 클래스에 Object 타입의 조회를 위한 peek() 메서드 정의해주기

 

Stack.java

ㄴ empty() 메서드도 참고하여 정의하기

 

Stack.java

ㄴ this.size() == 0   =>   empty() 메서드 이용

 

MenuPrompt.java

ㄴ Stack 에 정의되어있는 peek() 메서드 이용

ㄴ printMenu() 메서드는 현재 메뉴의 제목을 출력함

ㄴ menus.peek()를 사용하여 menus 스택의 가장 위에 있는 요소를 가져와서 출력

=> peek() 메서드는 요소를 스택에서 제거하지 않고 가져오는 것이므로, 스택에서 요소가 제거되지 않고 현재 메뉴 제목만 출력됨

 

MenuPrompt.java

ㄴ removeBreadcrumbs() 메서드는 breadcrumbs 스택과 menus 스택에서 최근에 추가된 메뉴 경로와 메뉴를 제거하는 역할

ㄴ breadcrumbs.pop()을 호출하여 가장 위에 있는 메뉴 경로를 제거하고, menus.pop()을 호출하여 가장 위에 있는 메뉴를 제거

ㄴ 추가할 때 menu 도 같이 추가하므로 삭제 시에도 menus 도 같이 꺼내줘야함

=> 가장 최근에 추가된 메뉴 경로와 해당 메뉴가 제거되어 이전 메뉴 경로와 이전 메뉴로 돌아갈 수 있게 됨

 

App.java

ㄴ printMenu() => getMenu() 로 변경

 

App.java

ㄴ StringBuilder 사용하여 문자열 저장하여 리턴하기

 

MemberHandler.java

ㄴ printMenu() => getMenu() 로 변경 후 StringBuilder 이용

 

=> BoardHandler 클래스도 마찬가지로 변경해주기

 

 

App.java

ㄴ appendBreadcrumbs(String title, String menu) 메서드에 String 타입인 "메인" 과 getMenu() 메서드의 실행결과를 아규먼트로 넘겨줌

 

App.java

ㄴ MenuPrompt 클래스에 정의한 printMenu() 를 실행시킴

=> menu 를 하나씩 모두 조회하여 출력 (peek())

 

App.java

ㄴ MenuPrompt 클래스에 정의한 printMenu() 를 실행시킴

=> menu 를 하나씩 모두 조회하여 출력 (peek())

 

MemberHandler.java

ㄴ MenuPrompt 의 printMenu() 메서드를 실행해야 하므로 prompt 붙여주기

 

Queue 적용

MenuPrompt 클래스에 입력한 명령어의 history 기능을 추가

MenuPrompt.java

ㄴ 사용자가 입력한 명령어를 history 에 보관하기 위해 commandHistory 인스턴스 생성

 

MenuPrompt.java

ㄴ Queue 클래스의 offer(Object value) 메서드를 이용하여 사용자가 입력한 명령어를 history 에 보관

 

MenuPrompt.java

ㄴ command 라는 문자열 변수를 선언하고 여기에 titleBuilder 에 받은 값을 문자열로 변경하여 저장

ㄴ commandHistory 라는 Queue 인스턴스에 command 를 추가함

ㄴ 리턴값은 titleBuilder 에 받은 값을 문자열로 변경한 값

 

MenuPrompt.java

ㄴ commandHistory 에 사용자가 입력한 명령어가 10개 담겼다면 가장 처음에 들어간 값부터 삭제

=> Queue 의 poll() 메서드 이용

 

MenuPrompt.java

ㄴ 사용자가 입력한 commandHistory 를 모두 출력하는 printCommandHistory() 메서드 생성

 

MenuPrompt.java

ㄴ 사용자가 입력한 명령어를 모두 command 에 담는데, "history" 라는 문자열을 입력할 경우 printCommandHistory() 메서드를 실행하고 빈문자열을 리턴

ㄴ 그렇지 않다면 while(true) 문을 나감

 

MenuPrompt.java

ㄴ command 를 처음에는 null 로 선언

ㄴ 입력된 명령어가 "history" 가 되지 않는 이상 command 에 계속 저장됨

 

ㄴ 실행 결과 => "메뉴 번호가 옳지 않습니다" 가 출력돼서 아래처럼 코드 수정

 

MenuPrompt.java

ㄴ MenuPrompt 클래스의 inputMenu() 메서드 수정 (return ""; 제거)

 

ㄴ 잘 출력됨을 확인하였지만 숫자로만 출력돼서 어떤 메뉴인지 알기 힘듦 => 수정 필요

 

MenuPrompt.java

ㄴ 메뉴의 title 명을 알기위해 findMenuTitle 메서드 추가

 

MenuPrompt.java

ㄴ peek() 메서드의 리턴값이 Object 이므로 String 으로 형변환 필요

 

MenuPrompt.java

ㄴ 이를 통해 해당 메서드가 메뉴 타이틀을 가져온다는 것을 확인할 수 있음

 

MenuPrompt.java

ㄴ inputMenu() 메서드 에서 변수 수정 => menuTitle -> menuItem

 

MenuPrompt.java

ㄴ menuItem 변수에 command 에 해당하는 메뉴가 있는지 findMenuTitle(command) 메서드를 통해 그 메뉴 이름을, 없으면 null 을 리턴 받아 넣음

ㄴ 해당 리턴 값이 null 이 아니라면 commandHistory 에 Queue 의 offer(Object value) 메서드를 이용해서 다음과 같이 출력하도록 만듦 => 해당 menuItem 이 어떤 메뉴의 메뉴이름인지 알기 위함

ㄴ 해당 리턴 값이 null 이라면 command 그대로를 노출시킴

ㄴ 10개 이상이 되면 가장 처음에 들어갔던 값 부터 삭제됨

 

MenuPrompt.java

ㄴ "menu" 라는 문자열을 입력 받으면 printMenu() 메서드를 실행하라는 기능을 MenuPrompt 클래스에서 구현

 

App.java

ㄴ MemberHandler, BoardHandler, ItemHandler 도 마찬가지로 "menu" 라는 문자열을 입력하면 출력해주는 기능은 MenuPrompt 에서 다룸

 

MenuPrompt.java

ㄴ 메뉴 번호 유효성을 MenuPrompt 클래스에서 검사하도록 구현

=> App, MemberHandler, BoardHandler, ItemHandler 에 있는 해당 내용은 제거해줌 (MenuPrompt 에서 모두 처리 가능)

=> findMenuTitle -> findMenuItem 으로 메서드명 변경

 

App.java

=>

ㄴ if else 문 switch case 문으로 변경