[Beyond SW] 20251103

이경민·2025년 11월 4일

한화시스템 Beyond SW

목록 보기
24/40

Stack


후입선출(LIFO)의 자료구조로 push(), pop(), peek() 자료를 처리할 수 있다.

stack.peek() : 값이 어디에 있는지 확인
stack.pop() : 더이상 없는 값일때 pop을 하면 EmptyStackException 발생

Queue

  • FIFO(First In First Out) 구조
  • 큐는 Front와 Rear를 정하고 한 곳에는 삭제만, 다른 한 곳에서는 삽입 연산만 처리한다.
  • Queue 인터페이스를 상속받는 하위 인터페이스 들은 Deque, BlockingQueue, BlockingDeque, TreansferQueue 등 다양하지만 대부분의 큐는 LinkedList를 이용한다
/* Queue */
        Queue<String> que = new LinkedList<>();
/*큐에 데이터를 넣을 때는 offer 메소드를 사용한다.*/
        que.offer("first");
        que.offer("second");
        que.offer("third");
        que.offer("fourth");
        que.offer("fifth");
        System.out.println("queue : " + que);

peek() : 해당 큐의 가장 앞에 있는 요소(먼저 들어온 요소)를 반환
poll() : 해당 큐의 가장 앞에 있는 요소(먼저 들어온 요소)를 반환하고 제거. 큐에서 반환할 값이 없을 경우 null 반환

Priority Queue

: 선입선출 + 정렬의 개념을 가져갈 수 있다.
PriorityQueue<String> que = new PriorityQueue<>(Collections.reverseOrder()) : String 기준대로 문자열 내림차순
PriorityQueue<String> pq = new PriorityQueue<>() : String 기준대로 문자열 오름차순

Set

Set이란 집합처럼 중복되지 않는 데이터를 저장하는 자료구조이다.
중복을 허용하지 않는 다는 것은 중복 저장을 허용하지 않는다는 뜻이며, null도 하나의 null만 저장한다.
-> 이미 있는 중복된값을 add하면 변화 없음
Set에는 크게 TreeSet, HashSet, LinkedHashSet이 있다.

HashSet

해시 테이블을 이용하여 데이터를 저장하는 구조
Set의 특징을 가지고 있으며 중복된 값이 저장되지 않는다.

  • Map의 특성 중 중복 키 값이 있을 수 없다는 특징을 계승한다.
  • 인덱스가 아닌 키 값을 이용하여 데이터에 저장과 접근을 한다.
  • 삽입 삭제가 빈번한 경우 사용할 수 있다.
  • set에 저장된 자료는 넣는 순서를 보장할 수 없다. (실행할때마다 결과가 다르게 나올 수 있음)
        /* Set의 데이터를 순회하는 방법 */
        /* 1. 배열로 변경 */
        Object[] arr = hset.toArray();
        for(int i = 0; i < arr.length; i++){
            System.out.println(i+" : "+arr[i]);
        }
        /* 2. Iterable의 iterator메소드(반복자) */
        Iterator<String> iter = hset.iterator();
        while(iter.hasNext()){
            System.out.println(iter.next());
            iter.remove(); //iterator의 remove를 활용하면 순회하면서 제거할 수 있다.
        }
        System.out.println("hset : " + hset);

        /* 3. 향상된  for문 */
        for (String str : hset) {
            System.out.println(str);
            // 반복 순회 도중 remove메소드를 사용하면 java.util.ConcurrentModificationException이 발생함
            // hset.remove(str);
        }
       

LinkedHashSet

저장 당시의 순서를 유지하는 특성을 가지고 있다. (중복제거 + 순서유지)

TreeSet

자동 오름차순 정렬을 하며 이진 트리의 형태로 요소를 저장하고 있다.
String 클래스에 implements Comparable을 통해 compareTo 메소드가 오버라이딩 되어있는 기준으로 정렬된다.

  • TreeSet 클래스는 데이터가 정렬된 상태로 저장되는 이진 검색 트리의 형태로 요소를 저장한다.
  • 이진 검색 트리는 데이터를 추가하거나 제거하는 등의 기본 동작 시간이 매우 빠르다.

    로또 코드

Set<Integer> lotto = new TreeSet<>();

        while (lotto.size() < 6) {
            lotto.add((int)(Math.random() *45)+1);
        }

Map

키와 값을 하나의 쌍으로 저장하는 자료구조이다. 키는 실제 데이터를 찾기 위한 역할을 한다.
Map의 종류로는 HashMap, HashTable, TreeMap 등이 있다.

HashMap

기존에 있는 key값에 다른값을 넣으면 > 값이 업데이트 됨
키값만 다르면 값은 동일해도 상관 없음

/* HashMap */
        HashMap hmap = new HashMap();
        hmap.put("one", new Date());
        hmap.put(12, "red apple");
        hmap.put(33, 123);
        System.out.println("hmap = " + hmap);
        hmap.put(12, "yellow apple");
        System.out.println("hmap = " + hmap); // 기존에 있는 key값에 다른값을 넣으면 > 값이 업데이트 됨
        hmap.put(11, "yellow apple");
        System.out.println("hmap = " + hmap); // 키값만 다르면 값은 동일해도 상관 없음

List>Array List
값 추가 : add()
값 삭제 : remove()
특정값 가져오기 : get(인덱스)
값 수정 : set()


Map
값 추가 : put()
값 삭제 : remove()
특정값 갑져오기 : get(키값)
값 수정 : 동일한 키값에 다른 값 넣기

Properties

HashMap과 거의 유사하지만 key와 value 모두를 String으로만 사용할 수 있는 자료구조이다. 설정파일의 값을 읽어서 애플리케이션에 적용할 때 사용

  • 프로그램 환경 설정과 관련된 데이터를 읽어올 때 주로 쓴다.
  • Key, Value 모두 String 이기 때문에 제네릭이 필요하지 않다.
Properties prop = new Properties();
        prop.setProperty("driver", "com.mysql.cj.jdbc.Driver");
        prop.setProperty("url", "jdbc:maria://localhost:3306/test");
        prop.setProperty("user", "student");
        prop.setProperty("password", "student");

        System.out.println(prop);

        try {
            prop.store(new FileOutputStream("src/main/java/com/ohgiraffers/section03/map/run/driver.dat")
                    , "jdbc driver(comment");
            prop.store(new FileWriter("src/main/java/com/ohgiraffers/section03/map/run/url.properties")
                    , "jdbc driver(comment-properties");
            prop.store(new FileOutputStream("src/main/java/com/ohgiraffers/section03/map/run/url.xml")
                    , "jdbc driver(comment-xml");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        System.out.println("======================");
        Properties prop2 = new Properties();
        System.out.println("prop2: " + prop2);
        try {
        //            prop2.load(new FileInputStream("src/main/java/com/ohgiraffers/section03/map/run/driver.dat");
        //            prop2.load(new FileReader("src/main/java/com/ohgiraffers/section03/map/run/url.properties"));
            prop2.loadFromXML(new FileInputStream("src/main/java/com/ohgiraffers/section03/map/run/url.xml"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        System.out.println("prop2: " + prop2);

        // Properties 객체에 값을 추가할때는 setProperty(), 값을 가져올때는 getProperty()
        System.out.println("driver : " + prop2.getProperty("driver"));
        System.out.println("url : " + prop2.getProperty("url"));
        System.out.println("user : " + prop2.getProperty("user"));
        System.out.println("password : " + prop2.getProperty("password"));

ENUM

관련이 있는 상수의 집합의 클래스를 의미한다. 각각의 열거 상수는 열거 객체로 생성된다.

변하지 않는 것을 상수라고 하고 자바에서는 final 이라는 키워드로 선언한다.

  • 상수는 값이 한번 정해지면 변경할 수 없다.
  • 변수와 다르게 상수명은 모든 문자를 영어 대문자로 작성해야한다.

기본생성자를 가질 수 있다.
default와 private 접근제한자 사용이 가능하지만 외부에서 호출은 불가능하다(묵시작으로 private)
enum 타입은 고정된 상수들의 집합으로, 런타임이 아닌 컴파일 시에 모든 값이 결정되어 있어야 한다.
따라서 다른 클래스에서 enum 타입에 접근해 동적으로 생성자를 이용해 어떤 값을 전달해 줄 수 없기 때문이다.
단, 생성자를 가질 시 열거형 상수 선언 마지막에 세미콜론을 붙여야한다.

  1. 열거 타입은 싱글톤 방식으로 구현되기 때문에 인스턴스의 생성이나 확장이 되지 않는다.
    즉, 인스턴스가 통제되며 하나만 존재하는 것이 보장된다.
  2. 열거 타입은 컴파일 타임 타입 안정성을 높여준다.
    enumTest() 는 FoodsEnum 타입으로 받도록 선언해 두었기 때문에 다른 타입의 매개변수가 들어오는 경우 컴파일 에러를 발생시켜 준다.
  3. 열거 타입은 상수 이름을 문자열로 출력할 수 있다.
  4. 열거 타입에 메소드나 필드를 추가 할 수 있다.
    추가로 열거 타입은 근본적으로 불변이라 모든 필드는 final 이어야 한다
  5. 열거 타입도 클래스이기 때문에 toString() 을 재정의하여 사용할 수 있다.
  6. 열거 타입에 선언된 상수 하나를 제거하더라도 클라이언트에 영향을 주지 않는다.
    혹시나 삭제된 상수를 참조하고 있는 곳이 있다면 컴파일 에러를 출력해주기 때문에 안전하다.
  7. 열거 타입 내에 선언된 상수들을 순회할 수 있다.

/* Enum type의 메소드
        1. values() : 열거 타입의 모든 값을 배열로 반환
         */
        for(EnumType enumType : EnumType.values()){
            System.out.println("enumType = "+enumType);
        }

        /* 2. valueOf(): 해당 이름을 가진 열거 타입 상수 반환 */
        for(EnumType enumType : EnumType.values()){
            if (enumType == EnumType.valueOf("JAVA")) {
                System.out.println("enumType = "+enumType);
            }
        }

        /* 3. ordinal() : 열거 타입의 상수의 순서를 리턴 */
        for(EnumType enumType : EnumType.values()){
            System.out.println("ordinal = " + enumType.ordinal());
        }

        /* 4. name() : 열거 타입의 문자열 리턴 */
        System.out.println("name : " + EnumType.MARIADB.name());
        System.out.println("name : " + EnumType.MARIADB.toString());

EnumSet을 활용하여 enum을 Set 자료구조로 다룰 수 있다.

EnumSet<FoodsEnum> foods = EnumSet.noneOf(FoodsEnum.class);
                                         ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
                                            ->FoodsEnum의 메타데이터

람다

자바에서는 메소드를 독립적으로 선언하는 것이 불가능하다.
클래스나 인터페이스 내부에서만 선언되기 때문에 메소드를 가지는 클래스나 인터페이스가 필요하다.
람다식은 그 중 인터페이스를 활용하게 된다.
하지만 모든 인터페이스에 메소드를 작성한다고 람다식을 활용할 수 있는 것은 아니다.
인터페이스 내부에 하나의 추상메소드가 선언된 인터페이스만 람다식의 타겟이 될 수 있다. 람다식 사용 시 인터페이스 하나당 하나의 추상메소드만 가능!!
이러한 인터페이스를 함수적 인터페이스(functional interface)라고 하며,
해당 조건을 만족하는지를 컴파일 시점에 체크해주는 기능이 @FunctionalInterface어노테이션이다.

내부 인터페이스를 활용하여 파일 너무 많아지는 것 방지

함수적 인터페이스

  • Consumer : 리턴값이 없는 accept() 메소드를 가지고 있다.
  • Supplier : 매개변수가 없고 리턴 값이 있는 getXXX() 메소드를 가지고 있다.
  • Function : 매개변수와 리턴값이 있는 applyXXX() 메소드를 가지고 있다. (매개변수를 리턴값으로 매핑하는 역할)
  • Operator : Function과 똑같이 applyXXX() 메소드를 가지고 있다. 차이점은 매개변수로 연산을 한 후 통일타입으로 리턴한다.
  • Predicate : 매개변수와 boolean 값을 반환하는 testXXX()를 가지고 있다. (매개변수를 활용하여 boolean 반환)

Consumer

Consumer 함수적 인터페이스의 특징은 리턴 값이 없는 accept() 메소드를 가지고 있다는 것이다.
accept() 메소드는 단지 매개 변수로 넘어온 값을 소비하는 역할만 한다. 소비한다는 것은 리턴값이 없다는 말이다.

인터페이스 명추상 메소드설명
Consumervoid accept(T t)객체 T를 받아서 소비한다.
BiConsumer<T, U>void accept(T t, U u)객체 T, U를 받아 소비한다.
intConsumervoid accept(int value)int 값을 받아 소비한다.
DoubleConsumervoid accept(double value)double 값을 받아 소비8한다.
LongConsumervoid accept(long value)long 값을 받아 소비한다.
ObjIntConsumervoid accept(T t, int value)객체 T와 int 값을 받아 소비한다.
ObjDoubleConsumervoid accept(T t, double value)객체 T와 double 값을 받아 소비한다.
ObjLongConsumervoid accept(T t, long value)객체 T와 long 값을 받아 소비한다.

Supplier

Supplier 함수적 인터페이스는 매개변수가 없고 리턴 값이 있는 getXXX() 메소드를 가지고 있다.
이 메소드는 실행 되면 호출한 곳으로 값을 리턴해준다.

Function

Function 함수적 인터페이스의 특징은 매개변수와 리턴값이 있는 applyXXX() 를 가지고 있다는 것이다.
이 메소드들은 매개 변수 타입과 리턴 타입에 따라서 다양한 메소드들이 있다.

Operator

Operator 함수적 인터페이스는 Function 과 똑같이 작동한다. 매개변수와 리턴값이 있는 applyXXX() 메소드를 가지고 있다.
Function 과 다른 점은 매개변수와 동일한 타입으로 리턴을 한다.

Predicate

Predicate 함수적 인터페이스는 매개 변수와 boolean 리턴 값이 있는 testXXX() 를 가지고 있다.
이 메소드들은 매개변수 값을 이용해 true 또는 false 를 리턴하는 역할을 한다.

메소드 참조

함수형 인터페이스를 람다식이 아닌 일반 메소드를 참조시켜 선언하는 방법이다.
일반 메소드를 참조하기 위해서는 3가지 조건을 만족해야한다.
함수형 인터페이스의 매개변수 타입/개수/반환 형이랑 메소드의 매개변수 타입/개수/반환 형이 같아야 한다.

[메소드 참조 표현식]
클래스이름 :: 메소드이름
참조변수이름 :: 메소드이름

0개의 댓글