기초단계/JAVA

2022.12.01 JAVA 컬렉션 자료구조

춘핑이 2022. 12. 2. 21:37

15. 컬렉션 자료구조

15.3 Set컬렉션

인덱스로 관리x 중복x 저장순서 유지x null은 하나만 저장할수있다.
Set컬렉션은 수학의 집합에 비유될 수 있다. 집합은 순서와 상관없고 중복이 허용되지않기때문이다.
구슬주머니라고 보면된다.

set컬렉션에는 HashSet, LinkedHashSet, TreeSet 등이 있는데 인덱스로 관리하지 않기때문에 인덱스가 매개값으로 갖는 메소드가 없다.
Set
get()이 없음 하나씩 가져올수없음! -> iterator()
리턴타입 인터페이스 Iterator타입 hasNext()가져올게 있느냐?, next()가져와라로 가져올수있음. 참조만 가져오는것임.
Iterator iterator() 저장된 객체를 한번씩 가져오는 반복자리턴

15.3.1 HashSet

Set set = new HashSet(); //E에 저장된 타입의 객체만 저장
Set set = new HashSet<>(); //E에 저장된 타입의 객체만 저장
Set set = new HashSet() //모든 타입의 객체를 저장

타입파라미터E에는 HashSet에 저장하고 싶은 객체 타입을 지정하면된다.
HashSet은 동일한 객체는 중복저장하지 않는다.
여기서 동일한 객체란 동등객체를 말하는데 HashSet은 다른객체라도 hashCode()메소드 리턴값이 같고 equals()메소드가 true를 리턴하면 동일한 객체라고 판단한다.

package ch15.sec03.exam01;

import java.util.*;

public class HashSetExample {
public static void main(String[] args) {
    //HashSet 컬렉션 생성
    Set<String> set = new HashSet<String>();

    //객체 저장
    set.add("Java");
    set.add("JDBC");
    set.add("Servlet/JSP");
    set.add("Java");            //<-- 중복 객체이므로 저장하지 않음
    set.add("iBATIS");

    //저장된 객체 수 출력
    int size = set.size();
    System.out.println("총 객체 수: " + size); //4나옴
}
}

이름과 나이가 동일할 경우 Member객체를 HashSet에 중복저장하지 않는다.
Member 클래스를 선언할때 이름과 나이가 동일하다면 동일한 해시코드가 리턴되도록 hashCode()를 재정의하고 equals()메소드가 true를 리턴하도록 재정의 했기때문이다.

package ch15.sec03.exam02;

public class Member {
public String name;
public int age;

public Member(String name, int age) {
    this.name = name;
    this.age = age;
}

//hashCode 재정의 문자열에 + 나이 같다면 계속동일하게 나옴.
@Override
public int hashCode() {
    return name.hashCode() + age;
}

//equals 재정의
@Override
public boolean equals(Object obj) {
    if(obj instanceof Member target) { //멤버만 넣을 것이니 멤머 객체인지 확인
        return target.name.equals(name) && (target.age==age) ;
    } else {
        return false;
    }
}}

 package ch15.sec03.exam01;

import java.util.*;

public class HashSetExample {
public static void main(String[] args) {
    //HashSet 컬렉션 생성
    Set<String> set = new HashSet<String>();

    //객체 저장
    set.add("Java");
    set.add("JDBC");
    set.add("Servlet/JSP");
    set.add("Java");            //<-- 중복 객체이므로 저장하지 않음
    set.add("iBATIS");

    //저장된 객체 수 출력
    int size = set.size();
    System.out.println("총 객체 수: " + size); //4나옴
}}

 package ch15.sec03.exam03;

import java.util.*;

public class HashSetExample {
public static void main(String[] args) {
    //HashSet 컬렉션 생성
    Set<String> set = new HashSet<String>();

    //객체 추가 4개문자열 추가
    set.add("Java");
    set.add("JDBC");
    set.add("JSP");
    set.add("Spring");

    //객체를 하나씩 가져와서 처리 특정객체 지정 불가
    Iterator<String> iterator = set.iterator();
    while(iterator.hasNext()) {
        //객체를 하나 가져오기
        String element = iterator.next();
        System.out.println(element);
        if(element.equals("JSP")) {
            //가져온 객체를 컬렉션에서 제거
            iterator.remove(); //iterator는 참조만할뿐이지 Set에서 진짜로 삭제하는거임.
        }
    }
    System.out.println();

    //객체 제거
    set.remove("JDBC");

    //객체를 하나씩 가져와서 처리
    //for문안에서 확인하고 삭제하기 해버리면 개수모자라서 오류발생함! 
    -> 위 while문처럼 가져올게있는지 가져오기로 삭제하기.
    for(String element : set) {
        System.out.println(element);
    }
}}

set 컬렉션은 인덱스로 객체를 검색해서 가져오는 메소드가 없다. 대신 객체를 한개씩 반복해서 가져와야한다.
하나는 for 문을 이용하는 것임.
향상된 포문 for (E e : set){}
향상된 for문 :뒤에 올수 있는것? 배열, list, set -> Iterable를 상속하고 있다면 여기에 넣을 수 있음.
두번째 방법은 Set컬렉션의 iterator() 메소드로 반복자를 얻어 객체를 하나씩 가져오는 것임.
Set set = new HashSet();
Iterator iterator() = set.iterator();
다음메소드 제공
boolean hasNext() / 가져올 객체가 있으면 true리턴 없으면 false리턴
E next() / 컬렉션에서 하나의 객체를 가져온다.
void remove() / next()로 가져온 객체를 Set컬렉션에서 제거한다.
while(iterator.hasNext()){E e = iterator.next();} 반복문에서 true면 가져와 다가져오면 false 멈춤.

15.4 Map 컬렉션

Map컬렉션은 키와 값으로 구성된 엔트리 객체를 저장한다. 여기서 키와 값음 모두 객체이다.
키는 중복으로 저장할수 없지만 값은 중복으로 저장할수있다. 키로 찾기때문.
기존에 저장된 키와 동일한 키로 값을 저장하면 기존의 값이 없어지고 새로운 값으로 대치된다.

Map 컬렉션에는 HashMap, Hashtable, LinkedHashMap, Properties, TreeMap등이 있다.
공통적으로 사용하는 메소드는 다음과 같다.

저장할때 put
제거할때는 전부다 제거

Set<Map.Entry<K,V>> entrySet() // Set타입의 객체에 entry가 들어가있다.
Set keySet() //키들로만 Set타입의 객체로 만들기
Collection values() // 값들만 모아서 Collection타입으로 전환

15.4.1 HashMap

키와 값으로 저장할때 키로 사용할 객체가 동등객체인지 판단
Map<키타입, 값타입> map = new HashMap<키타입, 값타입>();
Map<String, Integer> map = new HashMap<String, Integer>();
Map<String, Integer> map = new HashMap<>(); //같으면 역시나 생략가능
Map map = new HashMap(); //아무거나

package ch15.sec04.exam01;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class HashMapExample {
public static void main(String[] args) {
    //Map 컬렉션 생성
    Map<String, Integer> map = new HashMap< >();
    //타입파라미터에 기본타입은 못넣음 Integer 중요!

    //객체 저장 
    map.put("신용권", 85);
    map.put("홍길동", 90);
    map.put("동장군", 80);
    map.put("홍길동", 95); //키값이 홍길동 중복되므로 나중에 넣은 95만 저장
    System.out.println("총 Entry 수: " + map.size());
    System.out.println();

    //키로 값 얻기
    String key = "홍길동";
    int value = map.get(key); //자동언박싱
    System.out.println(key + ": " + value);
    System.out.println();

    //키 Set 컬렉션을 얻고, 반복해서 키와 값을 얻기
    Set<String> keySet = map.keySet(); //키가 스트링이라 셋 스트링으로함
    Iterator<String> keyIterator = keySet.iterator();
    //반복자얻어서 반복
    while (keyIterator.hasNext()) { 
        String k = keyIterator.next(); //키얻음
        Integer v = map.get(k); //위에서 얻은 키로 밸류값얻기
        System.out.println(k + " : " + v);
    }
    System.out.println();

    //엔트리 Set 컬렉션을 얻고, 반복해서 키와 값을 얻기
    //Set<Entry> -> Set<Entry<String, Integer>>된거임.
    Set<Entry<String, Integer>> entrySet = map.entrySet();
    Iterator<Entry<String, Integer>> entryIterator = entrySet.iterator();
    while (entryIterator.hasNext()) {
        Entry<String, Integer> entry = entryIterator.next();
        String k = entry.getKey();
        Integer v = entry.getValue();
        System.out.println(k + " : " + v);
    }
    System.out.println();

    //키로 엔트리 삭제- 키값주면 그 키로 엔트리삭제함.
    map.remove("홍길동");
    System.out.println("총 Entry 수: " + map.size());
    System.out.println();
}}

15.4.2 Hashtable

Hashtable은 HashMap과 동일한 내부구조를 가지고 있다.
차이점은 Hashtable은 동기화된 메소드로 구성되어 있기때문에 멀티스레드가 동시에 메소드를 실행할수없다.
따라서 멀티스레드 환경에서도 안전하게 객체를 추가 삭제할수있다.
== Vector와 ArrayList차이 처럼
HashMap사용시 오류발생가능함.

Map<String, Integer> map = new Hashtable<String, Integer>();
Map<String, Integer> map = new Hashtable<>(); //같으면 역시나 생략가능
Map map = new Hashtable(); //아무거나

package ch15.sec04.exam02;

import java.util.Hashtable;
import java.util.Map;

public class HashtableExample {
public static void main(String[] args) {
    //Hashtable 컬렉션 생성
    Map<String, Integer> map = new Hashtable<>();

    //작업 스레드 객체 생성
    Thread threadA = new Thread() {
        @Override
        public void run() {
            //엔트리 1000개 추가
            for (int i = 1; i <= 1000; i++) {
                map.put(String.valueOf(i), i);
            }
        }
    };

    //작업 스레드 객체 생성
    Thread threadB = new Thread() {
        @Override
        public void run() {
            //엔트리 1000개 추가
            for (int i = 1001; i <= 2000; i++) {
                map.put(String.valueOf(i), i);
            }
        }
    };

    //작업 스레드 실행
    threadA.start();
    threadB.start();

    //작업 스레드들이 모두 종료될 때까지 메인 스레드를 기다리게 함
    try {
        threadA.join();
        threadB.join();
    } catch (Exception e) {
    }

    //저장된 총 엔트리 수 얻기
    int size = map.size();
    System.out.println("총 엔트리 수: " + size);
    System.out.println();
}}

15.4.3 Properties

맵계열의 구현클래스
Hashtable의 자식클래스이기때문에 이 특징을 그대로 가지고 있다.
그러나 얘는 키와 값을 모두 String타입으로 제한한 컬렉션이다.
용도는 주로 .properties 프로퍼티 파일(텍스트파일)을 읽을때 사용한다.

키=값의 형태로 보이는 형태임
일반 텍스파일과 다르게 ISO 8859-1 문자셋으로 저장되며 한글일경우 \u + 유니코드로 표현되어 저장

Properties properties = new Properties();
Map이기 때문에 맵처럼 가저와도되지만
Map인터페이스말고 properties의 메소드를 사용하기 위해서 Properties 객체로 생성함.

properties.load(Xxx.class.getResourceAsStream)"database.properties));
프로퍼티파일은 class파일과 함께 저장되어서 클래스파일을 기준으로 상대 경로를 이용해서 읽는 것이 편리하다.
12장 11절 리플렉션 참조
getResources는 절대 경로얻기
getResourceAsStream 파일을 오픈해서 리소스파일의 InputStream 리턴

실습위해 new - file로 properties파일 생성하기
driver=oracle.jdbc.OracleDirver
url=jdbc:oracle:thin:@localhost:1521:orcl
username=scott
password=tiger
admin=\uD64D\uAE38\uB3D9

package ch15.sec04.exam03;

import java.io.IOException;
import java.util.Properties;

public class PropertiesExample {
public static void main(String[] args) {
    //Properties 컬렉션 생성
    Properties properties = new Properties();

    //PropertiesExample.class와 동일한 ClassPath에 있는 database.properties 파일 로드
    // 컴파일 오류발생 해서 try catch를 해주는게 좋음. 
      책에서는 메인에 throws IOException했는데 이것은 별로 좋지 않은 방식임!
    try {
        properties.load(PropertiesExample.class.getResourceAsStream("database.properties"));
    } catch (IOException e) {}


    //주어진 키에 대한 값 읽기 리턴되는값, 키 모두 String 고정임
    String driver = properties.getProperty("driver");
    String url = properties.getProperty("url");
    String username = properties.getProperty("username");
    String password = properties.getProperty("password");
    String admin = properties.getProperty("admin");

    //값 출력
    System.out.println("driver : " + driver);
    System.out.println("url : " + url);
    System.out.println("username : " + username);
    System.out.println("password : " + password);
    System.out.println("admin : " + admin);
}}

15.5 검색 기능을 강화 시킨 컬렉션

검색기능을 강화시킨 TreeSet 과 TreeMap을 제공한다.
각각 Set와 Map이다.

15.5.1 TreeSet

TreeSet는 이진트리를 기반으로 한 Set컬렉션이다.
여러개의 노드가 트리 형태로 연결된 구조로 루트 노드라고 불리는 하나의 노드에서 시작해 각 노드에 최대 2개의 노드를 연결할수있는 구조를 가지고 있다.

TreeSet에 객체를 저장하면 다으 ㅁ사진처럼 정렬괸다. 부모 노드의 객체와 비교해서 낮은 것은 왼쪽자식노드에 높은것은 오른쪼고 자식 노드에 저장한다.
노드가 추가되면 left right추가

생성방법
TreeSet treeSet = new TreeSet();
TreeSet treeSet = new TreeSet<>();

Set타입 변수에 대입해도 되지만 TreeSet타입으로 대압한 이유는 검색 관련메소드가 TreeSet에 정의되어있기때문에 TreeSet에 특화된 메소드를 사용하기 위함이다.

Floor바닥 주어진 객체와 동등한 객체가 있으면 리턴 없으면 주어진 객체의 바로 아래의 객체를리턴
ceiling 천장 주어진 객체와 동등한 객체가 있으면 리턴 없으면 주어진 객체의 바로 위의 객체를리턴
desceningIterator() 내림차순으로 정렬된 반복자를 리턴

package ch15.sec05.exam01;

import java.util.NavigableSet;
import java.util.TreeSet;

public class TreeSetExample {
public static void main(String[] args) {
    //TreeSet 컬렉션 생성
    TreeSet<Integer> scores = new TreeSet< >();

    //Integer 객체 저장 
    //숫자 기준x로 그냥 저장해도 정렬을 시킴. 왼쪽 작은거 오른쪽 큰거 식
    scores.add(87);
    scores.add(98);
    scores.add(75);
    scores.add(95);
    scores.add(80);

    //정렬된 Integer 객체를 하나씩 가져오기
    for(Integer s : scores) {
        System.out.print(s + " ");
    }
    System.out.println("\n");

    //특정 Integer 객체를 가져오기
    System.out.println("가장 낮은 점수: " + scores.first()); //제일 낮은 객체 리턴
    System.out.println("가장 높은 점수: " + scores.last()); //제일 높은 객체 리턴
    System.out.println("95점 아래 점수: " + scores.lower(95)); // 95보다 작은거
    System.out.println("95점 위의 점수: " + scores.higher(95)); // 95보다 큰거
    System.out.println("95점이거나 바로 아래 점수: " + scores.floor(95)); //95있으면 95 없으면 바로아래
    System.out.println("85점이거나 바로 위의 점수: " + scores.ceiling(85) + "\n"); //85있으면 85 없으면 바로위

    //내림차순으로 정렬하기
    NavigableSet<Integer> descendingScores = scores.descendingSet();
    for(Integer s : descendingScores) {
        System.out.print(s + " ");
    }
    System.out.println("\n");

    //범위 검색( 80 <= ) //headSet, tailSet
    NavigableSet<Integer> rangeSet = scores.tailSet(80, true); //그값포함하면 true 아니면 false로하기
    for(Integer s : rangeSet) {
        System.out.print(s + " ");
    }
    System.out.println("\n");

    //범위 검색( 80 <= score < 90 )
    rangeSet = scores.subSet(80, true, 90, false); //그값포함하면 true 아니면 false로하기
    for(Integer s : rangeSet) {
        System.out.print(s + " ");
    }}}

15.5.2 TreeMap

TreeSet과 똑같지만 단순한 값이 아닌 키와 값으로 저장함.
TreeMap treeMap = new TreeMap();
TreeMap treeMap = new TreeMap<>();
역시나 특화된 메소드를 사용하기 위해 TreeMap 타입 사용
TreeSet과 유사하지만 Entry가 들어감.

package ch15.sec05.exam02;

import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.Set;
import java.util.TreeMap;

public class TreeMapExample {
public static void main(String[] args) {
    //TreeMap 컬렉션 생성
    TreeMap<String,Integer> treeMap = new TreeMap< >();

    //엔트리 저장 (키, 값) 키들로 정렬시킴.
    treeMap.put("apple", 10);
    treeMap.put("forever", 60);
    treeMap.put("description", 40);
    treeMap.put("ever", 50);
    treeMap.put("zoo", 80);
    treeMap.put("base", 20);
    treeMap.put("guess", 70);
    treeMap.put("cherry", 30);

    //정렬된 엔트리를 하나씩 가져오기
    //Map자체는 향상된 반복문에 못넣음. 그래서 Set으로 바꾸어서 저장하고 불러오기
    Set<Entry<String, Integer>> entrySet = treeMap.entrySet();
    for(Entry<String, Integer> entry : entrySet) {
        System.out.println(entry.getKey() + "-" + entry.getValue());
    }
    System.out.println();

    //특정 키에 대한 값 가져오기
    Entry<String,Integer> entry = null;
    entry = treeMap.firstEntry();
    System.out.println("제일 앞 단어: " + entry.getKey() + "-" + entry.getValue());
    entry = treeMap.lastEntry();
    System.out.println("제일 뒤 단어: " + entry.getKey() + "-" + entry.getValue());
    entry = treeMap.lowerEntry("ever");
    System.out.println("ever 앞 단어: " + entry.getKey() + "-" + entry.getValue() + "\n");

    //내림차순으로 정렬하기
    NavigableMap<String,Integer> descendingMap = treeMap.descendingMap();
    Set<Entry<String,Integer>> descendingEntrySet = descendingMap.entrySet();
    for(Entry<String,Integer> e : descendingEntrySet) {
        System.out.println(e.getKey() + "-" + e.getValue());
    }
    System.out.println();

    //범위 검색
    System.out.println("[c~h 사이의 단어 검색]");
    NavigableMap<String,Integer> rangeMap = treeMap.subMap("c", true, "h",    false); //c이상 h미만
    for(Entry<String, Integer> e : rangeMap.entrySet()) { //여기도 Set으로 바꾸어서 넣음.
        System.out.println(e.getKey() + "-" + e.getValue());
    }}}

15.5.3 Comparable과 Comparator

비교할수잇는 / 비교자
TreeSet에 저장되는 객체와 TreeMap에 저장되는 키 객체는 저장과 동시에 오름차순으로 정렬되는데
어떤 객체든 정렬될 수 있는 것은 아니고 객체가 Comparable인터페이스를 구현하고 있어야 가능하다.
Integer Double String 타입은 모두 Comparable을 구현하고 있기때문에 상관없는데 사용자 정의 객체를 저장할때는 반드시 Comparable을 구현해야한다.
Comparable인터페이스에는 compareTo()메소드가 정의되어있다. 따라서 사용자 정의 클래스에서 이 메소드를 재정의해서 비교결과를 정수값으로 리턴해야 한다.
Comparable<T> 객체
int compareTo(T o) 주어진 객체와 같으면 0을리턴 주어진 객체보다 적으면 음수를 리턴 주어진 객체보다 크면 양수를 리턴
양은 중요x 부호가 중요함. a.compareTo(b); 이런식으로 비교

package ch15.sec05.exam03;

public class Person implements Comparable<Person> {
public String name;
public int age;

public Person(String name, int age) {
    this.name = name;
    this.age = age;

}

@Override
public int compareTo(Person o) { 
    //Person객체에 주어진 o와 비교
    if(age<o.age) {
        return -1;
    }
    else if(age == o.age) {
        return 0;
    }
    else {
        return 1;
    }}}

package ch15.sec05.exam03;

import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

public class ComparableExample {
public static void main(String[] args) {
    //TreeSet 컬렉션생성
    //TreeSet<Person> treeSet = new TreeSet<>();
    //TreeMap 
    TreeMap<String, Integer> treeMap = new TreeMap<>();

    //객체 저장
    /*
    treeSet.add(new Person("홍길동", 45));
    treeSet.add(new Person("김자바", 25));
    treeSet.add(new Person("박지원", 31));
    */

    treeMap.put("홍길동", 45);
    treeMap.put("김자바", 25);
    treeMap.put("박지원", 31);

    //객체를 하나씩 가져오기
    /*
    for(Person person : treeSet) {
        System.out.println(person.name + ": " + person.age);
    }
    */
    Set<Entry<String, Integer>> entrySet = treeMap.entrySet();
    for(Entry<String, Integer> entry : entrySet) {
        System.out.println(entry.getKey() + ": " + entry.getValue());
    }}}

비교기능이 있는 Comparable 구현객체를 TreeSet에 저장하거나 TreeMap의 키로 저장하는 것이 원칙이지만 비교기능이 없는 객체를 저장하고 싶다면 방법이 없진않다.
비교자 Comparator를 다음과 같이 제공하면된다.
생성자의 매개값으로 비교자 제공 여기서 비교자의 역할? E타입 의 객체를 비교해줌.

비교자는 Comparator 인터페이스를 구현하면된다. Comparator에는 compare()메소드가 정의되어있다. 비교자는 이 메소드를 재정의해서 비교결과를 정수값으로 리턴하면된다.
int compare(T o1, T o2) o1과 o2가 동등하다면 0리턴 o1이 o2보다 앞에 오게하려면 음수리턴 o1이 o2보다 뒤에 오게하려면 양수를 리턴

package ch15.sec05.exam04;

public class Fruit {
public String name;
public int price;

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

package ch15.sec05.exam04;

import java.util.Comparator;
public class FruitComparator implements Comparator<Fruit>{
@Override
public int compare(Fruit o1, Fruit o2) {
    if(o1.price < o2.price) {
        return -1;
    } else if (o1.price == o2.price) {
        return 0;
    } else {
        return 1;
    }}}

package ch15.sec05.exam04;

import java.util.TreeSet;

public class ComparableExample {
public static void main(String[] args) {
    //비교자를 제공한 TreeSet 컬렉션생성
    TreeSet<Fruit> treeSet = new TreeSet<Fruit>(new FruitComparator());

    //객체저장
    treeSet.add(new Fruit("포도", 3000));
    treeSet.add(new Fruit("수박", 10000));
    treeSet.add(new Fruit("딸기", 6000));

    //객체 하나씩 가져오기
    for(Fruit fruit : treeSet) {
        System.out.println(fruit.name + ": " + fruit.price );
    }}}

15.6 LIFO와 FIFO컬렉션

후입선출(LIFO Last In Fist Out)은 나중에 넣은 객체가 먼저 빠져나가고, 선입선출(FIFO First In First Out)은 먼저 넣은 객체가 먼저 빠져나가는 구조이다.
컬렉션 프레임 워크는 LIFO자료구조를 제공하는 스택 클래스와 FIFO자료구조를 제공하는 큐 인터페이스를 제공하고 있다.

스택을 이용한 대표적인 예가 JVM 스택 메모리 이다. 스택 메모리에 저장된 변수는 나주엥 저장된 것부터 제거된디ㅏ. 5장2절 참조
넣기 push 빼기pop


큐를 응용한 대표적인 예는 스레드풀의 작업큐이다. 작업큐는 먼저들어온 작업부터 처리한다.
넣기 offer 빼기 poll

15.6.1 Stack

LIFO자료구조를 구현한 클래스이다.
Stack<E> stack = new Stack<E>();
Stack<E> stack = new Stack<>();
주요메소드
E push(E item) 주어진객체를 스택에 넣는다.
E pop() 스택의 맨 위 객체를 빼낸다.

package ch15.sec06.exam01;

public class Coin {
private int value;

public Coin(int value) {
    this.value = value;
}

public int getValue() {
    return value;
}}

package ch15.sec06.exam01;

import java.util.Stack;

public class StackExample {

public static void main(String[] args) {
    //Stack 컬렉션 생성
    Stack<Coin> coinBox = new Stack<>();

    //동전넣기
    coinBox.push(new Coin(100));
    coinBox.push(new Coin(50));
    coinBox.push(new Coin(500));
    coinBox.push(new Coin(10));

    //동전하나씩 꺼내기
    //비어잇지않으면 반복
    while(!coinBox.isEmpty()) {
        Coin coin = coinBox.pop();
        System.out.println("꺼내온 동전: " + coin.getValue() + "원");
    }}}

15.6.2 Queue

Queue 인터페이스는 FIFO자료구조에서 사용되는 메소드를 정의하고 있다.
주요메소드
boolean offer(E e) 주어진객체를 큐에 넣는다.
E poll() 큐에서 객체를 빼낸다.

Queue인터페이스를 구현한 대표적인 클래스는 LinkedList이다. 그렇기땜누에 LinkedList객체를 Queue인터페이스 변수에 다음과 같이 대입할 수있다.
Queue<E> queue = new LikedList<E>();
Queue<E> queue = new LikedList<>();

package ch15.sec06.exam02;

public class Message {
public String command;
public String to;

public Message(String command, String to) {
    this.command = command;
    this.to = to;
}}

package ch15.sec06.exam02;

import java.util.LinkedList;
import java.util.Queue;

public class QueueExample {
public static void main(String[] args) {
    // Queue 컬렉션생성
    Queue<Message> messageQueue = new LinkedList<>();

    //메세지 넣기
    messageQueue.offer(new Message("sendMail", "홍길동"));
    messageQueue.offer(new Message("sendSMS", "신용권"));
    messageQueue.offer(new Message("sendKakaotalk", "강자바"));

    //메시지를 하나씩 꺼내어 처리
    while(!messageQueue.isEmpty()) {
        Message message = messageQueue.poll(); //offer된 순서대로 poll이 된다.
        switch(message.command) {
        case "sendMail":
            System.out.println(message.to + "님에게 메일을 보냅니다.");
            break;
        case "sendSMS":
            System.out.println(message.to + "님에게 SMS를 보냅니다.");
            break;
        case "sendKakaotalk":
            System.out.println(message.to + "님에게 카카오톡 보냅니다.");
            break;
        }}}}

15.7 동기화된 컬렉션

컬렉션프레음워크 대부분의 클래스들은 싱글스레드환겨엥서 사용ㄷ할수 있도록 설계되었따.
Vector와 Hashtable은 동기화된 메소드로 구성되어 있기때문에 멀티스레드 환경에서 안전하게 요소를 처리할 수 있지만. 다른겄들은 구성되지않아 멀티스레드환경에서 안전하지 안다.
리턴값으로 List Map을 받았는데 다른 동기화가 안된 ArrayList HashSet HashMap 등 컬렉션을 리턴받았을때 동기화된 컬렉션으로 바꾸어서 할필요가 있다.
비동기화된 메소드를 동기화된 메소드로 래핑하는 Collections의 synchronizedXXX()메소드를 제공한다.

package ch15.sec07;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class SynchronizedMapExample {
public static void main(String[] args) {
    // Map 컬렉션 생성
    Map<Integer, String> map = Collections.synchronizedMap(new HashMap<>());

    //작업스레드 객체 생성
    Thread threadA = new Thread() {
        @Override
        public void run() {
            //객체 100개추가
            for(int i=1 ; i <=1000 ; i++) {
                map.put(i, "내용"+i);
            }
        }
    };

    //작업스레드 객체 생성
    Thread threadB = new Thread() {
        @Override
        public void run() {
            //객체 100개추가
            for(int i=1001 ; i <=2000 ; i++) {
                map.put(i, "내용"+i);
            }
        }
    };

    //작업스레드 시행
    threadA.start();
    threadB.start();

    //작업스레드들이 모두 종료될때까지 메인 스레드를 기다리게함.
    try {
        threadA.join();
        threadB.join();
    } catch (Exception e) {}

    //저장된 총객체수 읽기
    int size = map.size();
    System.out.println("총 객체 수:" + size);
}}

15.8 수정할 수 없는 컬렉션

컬렉션이란 요소 추가 삭제할 수 있는데 이것을 못하게 하는것이다.
첫번째 방법은 정적메소드인 of()로 생성할 수 있다.
List<E> immutabeList = List.of(E...element);
Set<E> immutabeSet = Set.of(E...element);
Map<K,V> immutabeMap = Map.of(K k1, V v1, K k2, V v2 ...);

두번째 방법은 List Set Map인터페이스의 정적메소드인 copyOf()를 이용해 기존 컬렉션을 복사하여 수정할 수 없는 컬렉션을 만드는것이다.
List<E> immutabeList = List.copyOf(Collection<E> coll);
Set<E> immutabeSet = Set.copyOf(Collection<E> coll);
Map<K,V> immutabeMap = Map.copyOf(Map<K,V> map);

세번째 방법은 배열로부터 수정할 수 없는 List컬렉션을 만들수있다.
String[] arr = { "A" , "B" ,"C"}
List<String> immutableList = Arrays.asList(arr);

다 자주 사용한다. ArrayList를 DTO형태로 보내기 때문에 대부분 읽기만 가능하게 보냄.

package ch15.sec08;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class ImmutableExample {
public static void main(String[] args) {
    //List 불변 컬렉션 생성
    List<String> immutableList1 = List.of("A", "B", "C");
    //immutableList1.add("D"); (x)

    //Set 불변 컬렉션 생성
    Set<String> immutableSet1 = Set.of("A", "B", "C");
    //immutableSet1.remove("A"); (x)

    //Map 불변 컬렉션 생성
    Map<Integer, String> immutableMap1 = Map.of(
            1, "A",
            2, "B",
            3, "C"
            );
    //immutableMap1.put(4, "D"); (x)

    //List 컬렉션을 불변 컬렉션으로 복사
    List<String> list = new ArrayList< >();
    list.add("A");
    list.add("B");
    list.add("C");;
    List<String> immutableList2 = List.copyOf(list);

    //Set 컬렉션을 불변 컬렉션으로 복사
    Set<String> set= new HashSet< >();
    set.add("A");
    set.add("B");
    set.add("C");;
    Set<String> immutableSet2 = Set.copyOf(set);

    //Map 컬렉션을 불변 컬렉션으로 복사
    Map<Integer, String> map = new HashMap< >();
    map.put(1, "A");
    map.put(2, "B");
    map.put(3, "C");
    Map<Integer, String> immutableMap2 = Map.copyOf(map);

    //배열로부터 List 불변 컬렉션 생성
    //배열 래핑해서 List만드니까 리스트 밑 배열이라 새로 추가 불가능
    String[] arr = { "A", "B", "C" };
    List<String> immutableList3 = Arrays.asList(arr);
}}

2022.12.01 리뷰

공부 후 쉬고 밤에 작성하는데 잊어서 까먹고 하루 지나고 작성