23일차 배운 내용
(후,, 이 구간은 매우매우매우매우매우매우 중요한 부분!! 이거 못하면 죽쒀서 개 준거임 공부 다 배워놓고 실력 안생김)
1. 컬렉션 프레임워크
1) 컬렉션 프레임워크 소개
2) List 컬렉션
3) Set 컬렉션
4) Map 컬렉션
5) 검색 기능을 강화시킨 컬렉션
6) LIFO와 FIFO 컬렉션
7) 동기화된 컬렉션
8) 병렬 처리를 위한 컬렉션
[ 컬렉션 프레임워크 ]
( 매우매우매우매우매우매우 중요한 부분!! 이거 못하면 죽쒀서 개 준거임!! 공부 다 배워놓고 실력 안생김 )
[ 1 ] 컬렉션 프레임워크 소개
- 배열의 문제점
: 저장할 수 있는 객체의 수가 배열을 생성할 때 결정된다. 즉, 처음에 배열을 생성할 때 배열의 크기는 정해진다.
따라서 크기를 정하지 않고서는 배열을 사용할 수 없고 정해진 크기 이상 요소를 추가하기가 어렵다.
또한 객체를 삭제했을 때 해당 인덱스가 비게 되는데 배열 요소가 삭제된 공간은 그냥 텅 빈 공간으로 남기에
낱알 빠진 옥수수같은 배열이 되어 객체 저장 시 어디가 비어있고 어디가 채워져있는지 확인하는 코드로
확인해주면서 객체를 저장해줘야한다.
- 컬렉션 정의
: 컬렉션이란 사전적 의미로는 요소(객체)를 수집해서 저장하는 것을 말한다.
- 컬렉션 프레임워크
: 컬렉션 프레임워크란 몇가지 인터페이스를 통해 다양한 컬렉션 클래스를 이용할 수 있도록 하는 것이다.
[ 2 ] List 컬렉션
- 특징 : 인덱스로 관리한다. 즉, 데이터를 저장할 때 순서가 있다. 또한 데이터를 중복해서 저장이 가능하다.
- List 컬렉션으로 구현한 구현 클래스 : ArrayList, Vector, LinkedList (이 셋중 Vector 외 나머지 두개를 집중해서 이해하자)
1. ArrayList 구현 클래스
- 특징
1) 저장 용량(capacity)
- 초기 용량은 10 이지만 따로 초기용량 지정할 수 있다.
- 저장 용량을 초과한 객체들이 들어오면 배열의 길이, 크기가 자동적으로 늘어난다. 물론 크기 고정도 가능하다.
2) 객체 제거
<배열과의 차이점>
-배열 : 크기가 고정되어 있고 중간 배열의 요소값이 삭제되면 그냥 비어있는채로 배열 있음
-ArrayList : 크기가 고정되어 있지 않고 중간에 요소값이 삭제되면 바로 뒤 인덱스부터
앞으로 하나씩 당겨져서 채워진다.
import java.util.*;
public class ArrayListExample {
public static void main(String[] args) {
// List 만드는 방법 1
// ArrayList 구현클래스로 List 생성
// List<> list = new ArrayList<>();
// < > 에는 list 배열의 요소로 들어가는 값의 데이타타입을 적는다.
List<String> list = new ArrayList<String>();
// 인터페이스 = ArrayList 구현객체
list.add("Java");
list.add("JDBC");
list.add("Servlet/JSP");
list.add(2, "DataBase");
// list.add(인덱스, "문자열");
// 지정한 인덱스에 문자열 넣는 것을 의미
// 그러면 원래 그 인덱스에 있던 값은 다음 인덱스로 옮겨진다.
list.add("myBatis");
// ( ) 안에 문자열이 들어가는건 <String> 제네릭 타입으로 지정해서
// String 타입의 값이 배열에, ( )안에 들어가게 되는 것이다.
int size = list.size();
System.out.println("배열의 총 객체 수 : " + size);
System.out.println();
//list.get(int index) : 인덱스에 해당하는 값 리턴해주는 메서드
String skill = list.get(2);
// System.out.println(skill); 아래에 toString() 으로 출력하는 것과 같다.
System.out.println("2번 인덱스의 값: " + skill.toString());
for(int i = 0; i < list.size(); i++) {
String str = list.get(i);
System.out.println(i+ " : " + str);
}
System.out.println();
// 배열 요소 지워보기
// list.remove(int index);
// 인덱스에 해당하는 배열의 요소값 지우기
// 그러면 지워진 인덱스 다음 인덱스에 있는 값들이
// 저절로 하나씩 앞으로 당겨져 온다.
list.remove(2);
System.out.println(list);
list.remove(2);
System.out.println(list);
list.remove("myBatis");
System.out.println(list);
System.out.println();
// 이렇게 지우고 나면 0, 1번 인덱스의 배열 요소 값만 남게된다.
for(int i = 0; i < list.size(); i++) {
String str = list.get(i);
System.out.println(i + ": " + str);
}
System.out.println("--- 향상된 for문으로 남은 인덱스의 배열 값 출력 ---");
for(String str : list) {
System.out.println(str);
}
}
}
import java.util.Arrays;
import java.util.List;
public class ArraysAsListExample {
public static void main(String[] args) {
// List 만드는 방법 2
// List<> list = Arrays.asList();
List<String> list1 = Arrays.asList("홍길동", "신용권", "감자바");
// List 타입으로 값을 리턴한다.
for(String name: list1) {
System.out.println(name);
}
List<Integer> list2 = Arrays.asList(1, 2, 3); // 박싱 되어서 들어간다..?
// 배열 list 각 인덱스에 값이 들어가는 것이 아니라
// Integer 객체가 들어가는 것이다.
for(int value : list2) {
System.out.println(value);
}
}
}
2. Vector 구현 클래스
- 기본형
: List < E > list = new Vector < E > ( );
- ArrayList와 다르게 Vector는 동기화된(synchronized) 메소드로 구성되어 있기 때문에 멀티 스레드가 동시에
이 메서드들을 실행할 수 없고(ArrayList와의 차이점), 하나의 스래드가 실행을 완료해야만 다른 스레드를 실행할 수 있다.
그래서 멀티 스레드 환경에서 안전하게 객체를 추가 또는 삭제할 수 있다(thread safe).
그렇지만 한 스레드가 공유자원에 작업을 마치기 전까지 다른 스레드의 접근을 제한함으로
자료의 신뢰성을 보장받는 장점이 있으나 속도저하가 발생할 수 있다는 단점이 있다.
public class Board {
String subject;
String contents;
String writer;
public Board(String subject, String contents, String writer) {
this.subject = subject;
this.contents = contents;
this.writer = writer;
}
@Override
public String toString() {
return subject + ", " + contents + ", " + writer;
}
}
import java.util.List;
import java.util.Vector;
public class VectorExample {
public static void main(String[] args) {
List<Board> list = new Vector<Board>();
list.add(new Board("제목1", "내용1", "글쓴이1"));
list.add(new Board("제목2", "내용2", "글쓴이2"));
list.add(new Board("제목3", "내용3", "글쓴이3"));
list.add(new Board("제목4", "내용4", "글쓴이4"));
list.add(new Board("제목5", "내용5", "글쓴이5"));
// Board객체 list에 추가
list.remove(2); // 제목3 있는 객체 제거됨
list.remove(3); // 제목5 있는 객체 제거됨
for(int i = 0; i < list.size(); i++) {
Board board = list.get(i);
// list 배열의 요소들은 Board 타입형의 값들이다.
System.out.println(board.toString());
// 목록 출력
}
}
}
3. LinkedList 구현 클래스
- 기본형
: List <E> list = new LinkedList <E> ( );
- 특정 인덱스에서 객체를 제거하거나 추가하게 되면 바로 앞뒤 링크만 변경하면 된다.
빈번한 객체 삭제와 삽입이 일어나는 곳에서는 ArrayList보다 LinkedList를 사용하기 더 좋다.
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class LinkedListExample {
public static void main(String[] args) {
List<String> list1 = new ArrayList<String>();
List<String> list2 = new LinkedList<String>();
long startTime;
long endTime;
startTime = System.nanoTime();
for (int i = 0; i < 100000; i++) {
list1.add(0, String.valueOf(i));
// String.valueOf()
// int 형인 i값을 넣어서 String형의 값으로 리턴해주는 메서드
// 그냥 () 들어간 숫자값들이 그대로 ""문자열로 반환된다.
}
endTime = System.nanoTime();
System.out.println("ArrayList 걸린시간: " + (endTime - startTime) + " ns");
// 4877300 ns 출력
startTime = System.nanoTime();
for (int i = 0; i < 100000; i++) {
list2.add(0, String.valueOf(i));
}
endTime = System.nanoTime();
System.out.println("LinkedList 걸린시간: " + (endTime - startTime) + " ns");
// 1539900 ns 출력
}
}
[ 3 ] Set 컬렉션
- 특징
- 저장 순서가 유지되지 않는다 --> 순서 상관 없이 값이 저장된다.
- 객체를 중복 저장할 수 없다.
- 하나의 null만 저장이 가능하다.
- 주요 메서드
- Set 컬렉션에는 인덱스로 객체를 검색해서 가져오는 메서드가 없다.
대신, 전체 객체를 대상으로 한번씩 반복해 가져오는 반복자(Iterator)를 제공한다.
1. HashSet
- 기본형
: Set set = new HashSet();
- 동일 객체 및 동등 객체는 중복 저장하지 않는다.
- Set은 인덱스가 없어서 for문을 돌릴 수가 없다.
그런데 Set은 중복 저장 하면 안되므로 HashSet을 사용해서 중복된 값이 있는
hashCode() 와 equals() 메서드를 사용해서 값을 비교하여 확인해준다.
- 동등 객체 판단 방법
public class Member {
public String name;
public int age;
public Member(String name, int age) {
this.name = name;
this.age = age;
}
public boolean equals(Object obj) {
if(obj instanceof Member) {
Member member = (Member) obj;
return member.name.equals(name) && (member.age==age) ;
} else {
return false;
}
}
public int hashCode() {
return name.hashCode() + age;
}
}
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class HashSetExample1 {
public static void main(String[] args) {
Set<String> set = new HashSet<String>();
// 인터페이스 = 구현 객체;
set.add("Java");
set.add("JDBC");
set.add("Servlet/JSP");
set.add("Java"); // 중복된 자료에 overwrite한다.
set.add("myBatis");
int size = set.size();
System.out.println("총 객체 수 : " + size); // 4 출력 <-- 중복되는 값은 한번만 들어감
Iterator<String> iterator = set.iterator();
while(iterator.hasNext()) { // 값이 없을때까지 값 반환해줌
String element = iterator.next();
System.out.println(element);
// Java
// myBatis
// JDBC
// Servlet/JSP
// 위와 같이 출력됨
}
set.remove("JDBC");
set.remove("myBatis");
System.out.println("총 객체 개수 : " + size); // 2 출력
for(String element : set) {
System.out.println(element);
}
// set.clear() 메서드 : set의 모든 값들 삭제
set.clear();
if(set.isEmpty()) {
System.out.println("배열 비어 있음");
}
}
}
import java.util.HashSet;
import java.util.Set;
public class HashSetExample2 {
public static void main(String[] args) {
Set<Member> set = new HashSet<Member>();
set.add(new Member("홍길동", 30));
set.add(new Member("홍길동", 30));
System.out.println("총 객체수 : " + set.size());
}
}
* < 과제_Set을 이용한 로또 > *
Q. 1~45 사이의 정수중에서 6개의 숫자를 추출([7, 41, 25, 27, 29, 15])하는 로또 프로그램을 작성하세요. (단, Set 자료구조를 사용해서 중복 숫자가 나오지 않도록 작성하세요)
import java.util.HashSet;
import java.util.Iterator;
import java.util.Random;
import java.util.Set;
public class SetTest01 {
public static void main(String[] args) {
Set<Integer> set = new HashSet<Integer>();
Random r = new Random();
set.add(r.nextInt(45)+1);
set.add(r.nextInt(45)+1);
set.add(r.nextInt(45)+1);
set.add(r.nextInt(45)+1);
set.add(r.nextInt(45)+1);
int numCount = set.size();
while(numCount != 6) {
switch(numCount) {
case 0 :
set.add(r.nextInt(45)+1);
set.add(r.nextInt(45)+1);
set.add(r.nextInt(45)+1);
set.add(r.nextInt(45)+1);
set.add(r.nextInt(45)+1);
set.add(r.nextInt(45)+1);
case 1:
set.add(r.nextInt(45)+1);
set.add(r.nextInt(45)+1);
set.add(r.nextInt(45)+1);
set.add(r.nextInt(45)+1);
set.add(r.nextInt(45)+1);
case 2:
set.add(r.nextInt(45)+1);
set.add(r.nextInt(45)+1);
set.add(r.nextInt(45)+1);
set.add(r.nextInt(45)+1);
case 3:
set.add(r.nextInt(45)+1);
set.add(r.nextInt(45)+1);
set.add(r.nextInt(45)+1);
case 4:
set.add(r.nextInt(45)+1);
set.add(r.nextInt(45)+1);
case 5:
set.add(r.nextInt(45)+1);
}
}
Iterator<Integer> iterator = set.iterator(); // 저장된 객체를 한번씩 가져오는 반복자 리턴
while(iterator.hasNext()) {
int rottoNum = iterator.next();
System.out.println(" " + rottoNum);
}
}
}
[ 내가 만든 로또 당첨 코드 ]
import java.util.HashSet;
import java.util.Iterator;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;
public class SetTest01_Answer {
public static void main(String[] args) {
int n;
// Set : 입력되는 값을 순서 상관없이 저장한다.
Set s = new HashSet();
// TreeSet : 입력되는 값을 정렬하여 값을 저장한다.
// TreeSet은 값이 들어갈때 값이 비교되면서 이진트리 모양으로
// 값이 저장된다. 그러고 값을 꺼낼때
// 이진트리에서 가장 왼쪽에 있는 작은것부터 꺼내면서 정렬되도록 값을 꺼낸다.
TreeSet ts = new TreeSet();
Random r = new Random();
// 0.0 <= Math.random() : 임의의 실수 < 1.0
while(s.size() < 6) {
n = r.nextInt(45)+1; // 1 ~ 45 사이의 임의의 정수값
//nextInt() <- int 타입의 난수를 리턴
s.add(n); // set에서 중복을 허용하지 않는다.
}
ts.addAll(s); // s 를 정렬시켜주는 메서드,,?
System.out.println(ts);
}
}
[ 로또 답안 예시 ]
[ 4 ] Map 컬렉션
- 특징
- 키(key)와 값(value)으로 구성된 Map.Entry 객체를 저장하는 구조
- 키와 값은 모두 객체
- 키는 중복될 수 없지만 값은 중복 저장 가능
- 한줄로 말하자면, key 값은 중복 저장이 안되고 value 값은 중복 저장이 되고 데이터 저장 순서는 상관이 없고
key, value값이 한쌍으로 데이터 저장이 된다.
- Map 컬렉션을 구현한 구현 클래스
: HashMap, Hashtable, LinkedHashMap, Properties, TreeMap
- 주요 메서드
1. HashMap 구현 클래스
- 기본형 : Map map = new HashMap(); // K=키타입, V=값타입
- HashMap의 키로 사용할 객체는 hashCode()와 equals() 메소드를 재정의해서 동등 객체가 될 조건을 정해야 한다.
주로 키 타입은 String을 많이 사용하는데, String은 문자열이 같을 경 우 동등 객체가 될 수 있도록
hashCode()와 equals() 메소드가 재정의되어 있다
- 키와 값의 타입은 객체이므로 기본 타입을 사용할 수 없고 클래스 및 인터페이스 타입만 가 능하다.
// 사용자 정의 클래스
public class Student {
public int sno;
public String name;
public Student(int sno, String name) {
this.sno = sno;
this.name = name;
}
@Override
public int hashCode() {
return sno + name.hashCode();
//예) 1 + 33(value값인 name을 가지고 만든 해시코드값) = 34
}
// value값인 name을 가지고 해시코드 만들게 해서 sno값과 더한다.
// 이때 sno값과 value값인 name이 같으면 hashCode가 같게 되므로
// 둘다 더한 값도 같을 것이다. 그러면 같은것으로 보도록 hashCode() 메서드 재정의한것
@Override
public boolean equals(Object obj) {
if(obj instanceof Student) {
Student student = (Student)obj;
return (sno == student.sno) && (name.equals(student.name));
}else {
return false;
}
}
}
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class HashMapExample1 {
public static void main(String[] args) {
// Map 객체 생성
Map<String, Integer> map = new HashMap<String, Integer>();
// Map map = new HashMap(); <-- 이거는 키도 값도 다 Object타입으로 들어가는 것
// 이렇게 적으면 안된다..?
// 객체 저장
map.put("신용권", 85);
map.put("홍길동", 90);
map.put("민정장군", 80);
map.put("홍길동", 95);
System.out.println("총 Map Entry 수 : " + map.size()); // 3 출력
// key 값이 "홍길동"으로 중복되어 마지막에 넣은 "홍길동"인 객체만 들어가고
// 그 전 객체는 저장이 안된다.
// 객체 찾기
System.out.println("홍길동 : " + map.get("홍길동")); // 95 출력
// get() : key값이 "홍길동인" value값을 찾아 리턴해줌
System.out.println();
// 객체를 하나씩 처리하는 방법 : keySet()
// keySet() : key값 객체들을 Set으로 만들어버리는 메서드
Set<String> keySet = map.keySet();
Iterator<String> keyIterator = keySet.iterator();
while(keyIterator.hasNext()) {
String key = keyIterator.next();
Integer value = map.get(key);
System.out.println(key + ": " + value);
}
System.out.println();
// 객체 삭제
map.remove("홍길동");
System.out.println("총 Map.Entry 개수 : " + map.size());
System.out.println();
/** 객체를 하나씩 처리하는 다른 방법 : Map.EntrySet() **/
// key값도 value값도 Map 그 전체를 Set으로 만들어버리는 메서드
// Map은 key값은 String 타입으로, value값은 Integer 타입이므로
// Map.Entry<String, Integer> 이렇게 적은 것이다.
Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
Iterator<Map.Entry<String, Integer>> entryIterator = entrySet.iterator();
while(entryIterator.hasNext()) {
Map.Entry<String, Integer> entry = entryIterator.next();
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key + ": " + value);
}
System.out.println();
System.out.println("--- 객체 전체 삭제 후 Entry 개수 ---");
// 전체 객체 다 삭제
map.clear();
System.out.println("총 Map.Entry 개수 : " + map.size());
}
}
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class HashMapExample2 {
public static void main(String[] args) {
Map<Student, Integer> map = new HashMap<Student, Integer>();
// map에 키, 값 넣기
map.put(new Student(1, "홍길동"), 95);
map.put(new Student(1, "홍길동"), 95);
// 메서드 재정의 안한 상태에서는 위의 키값은 동일하지 않다고 본다.
// hashCode(), equals()메서드들을 재정의를 해서 키의 값이 중복하게 저장되지 않도록 해줘야한다.
System.out.println("총 Map.Entry 수 : " + map.size()); // 2 출력
// 사용자정의 클래스를 key값의 타입으로 사용하게되면
// 그 사용자정의 클래스에 hashCode(), equals() 메서드들을 모두
// 재정의해줘야 값이 중복되지 않게 Map에 저장할 수 있게 된다.
}
}
2. Hashtable 구현 클래스
- 키 객체 만드는 법은 HashMap과 동일하다.
- Hashtable은 스레드 동기화(synchronization)가 된 상태!
: 복수의 스레드가 동시에 Hashtable에 접근해서 객체를 추가, 삭제하더라도 스레드에 안 전(thread safe)
- ArrayList와 Vector의 관계가 HashMap과 Hashtable의 관계와 비슷하다.
import java.util.Hashtable;
import java.util.Map;
import java.util.Scanner;
public class HashtableExample {
public static void main(String[] args) {
Map<String, String> map = new Hashtable<String, String>();
map.put("spring", "12");
map.put("summer", "123");
map.put("fall", "1234");
map.put("winter", "12345");
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("아이디와 비밀번호를 입력해주세요");
System.out.print("아이디: ");
String id = scanner.nextLine();
System.out.print("비밀번호: ");
String password = scanner.nextLine();
System.out.println();
if (map.containsKey(id)) {
if (map.get(id).equals(password)) {
System.out.println("로그인 되었습니다");
break;
} else {
System.out.println("비밀번호가 일치하지 않습니다.");
}
} else {
System.out.println("입력하신 아이디가 존재하지 않습니다");
}
}
}
}
3. Properties 구현 클래스
- 특징
- 키와 값을 String 타입으로 제한한 Map 컬렉션
- Properties는 프로퍼티(~.properties) 파일을 읽어 들일 때 주로 사용
- 프로퍼티(~.properties) 파일 (<-- 중요하게 안다루신 내용임)
- 옵션 정보, 데이터베이스 연결 정보, 국제화(다국어) 정보를 기록
- 텍스트 파일로 활용
- 애플리케이션에서 주로 변경이 잦은 문자열을 저장
- 유지 보수를 편리하게 만들어 줌
- 키와 값이 = 기호로 연결되어 있는 텍스트 파일
- ISO 8859-1 문자셋으로 저장
- 한글은 유니코드(Unicode)로 변환되어 저장
/* database.properties */
driver=oracle.jdbc.OracleDirver
url=jdbc:oracle:thin:@localhost:1521:orcl
username=scott
password=tiger
import java.io.FileReader;
import java.net.URLDecoder;
import java.util.Properties;
public class PropertiesExample {
public static void main(String[] args) throws Exception {
// Properties 객체 생성 = Map<String, String>
Properties properties = new Properties();
String path = PropertiesExample.class.getResource("database.properties").getPath();
path = URLDecoder.decode(path, "utf-8");
// decode() : 한글들을 처리하기 위해 사용되는 메서드
properties.load(new FileReader(path));
// FileReader : File의 IO(입출력)을 담당하는 클래스
// load() : = 를 기준으로 = 앞은 key값으로 = 뒤는 value값으로 읽는 메서드
// [{"driver" : "oracle.jdbc.OracleDirver"}, {"username" : "scott"}, ....]
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
System.out.println("driver : " + driver);
System.out.println("url : " + url);
System.out.println("username : " + username);
System.out.println("password : " + password);
}
}
[ database.properties 파일로부터 값을 읽어 출력하는 예제 ]
* < 과제_게시판 만들기 > *
Q. 다음은 게시물을 관리하는 모듈이다. 특정 사용자가 등록한 게시물중에 비밀번호가 같으면 삭제할 수 있도록 코드를 작성하라.
//VO(Value Object) 클래스
//DTO(Data Transfer Object) 클래스
public class BoardVO extends Object {
//멤버변수
private String register;
private String subject;
private String email;
private String content;
private String passwd;
//생성자
public BoardVO(String register, String subject, String email, String content, String passwd) {
super();
this.register = register;
this.subject = subject;
this.email = email;
this.content = content;
this.passwd = passwd;
}
public String getRegister() {
return register;
}
public void setRegister(String register) {
this.register = register;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getPasswd() {
return passwd;
}
public void setPasswd(String passwd) {
this.passwd = passwd;
}
@Override
public String toString() {
return "작성자:" + register + ",이메일:" + email + ",제목:" + subject + ",글내용:" + content;
}
}
//DAO(Data Access Object) 클래스
import java.util.ArrayList;
import java.util.Scanner;
public class BoardSVC {
ArrayList<BoardVO> boardList;
public BoardSVC() {
boardList = new ArrayList();
}
//글 입력 처리 메소드
public void writeArticle(Scanner sc) {
System.out.println("게시판에 글을 작성 하세요.");
System.out.print("작성자:");
String register = sc.next();
System.out.print("이메일:");
String email = sc.next();
System.out.print("비밀번호:");
String passwd = sc.next();
System.out.print("제목:");
String subject = sc.next();
System.out.print("글내용:");
String content = sc.next();
BoardVO boardVO = new BoardVO(register, subject, email, content, passwd);
addArticle(boardVO);
}
//글 작성
private void addArticle(BoardVO boardVO) {
boardList.add(boardVO);
}
//글목록 출력
public void listArticles(Scanner sc) {
if (boardList.size() > 0) {
for (int i = 0; i < boardList.size(); i++) {
System.out.println(boardList.get(i).toString());
}
} else {
System.out.println("등록된 글이 없습니다.");
}
}
//삭제할 글의 작성자 및 비밀번호 입력하는 메소드
public void removeArticle(Scanner sc) {
//코드 작성
System.out.println("삭제할 글의 작성자와 비밀번호를 입력하세요.");
System.out.print("작성자: ");
String register = sc.next();
System.out.print("비밀번호: ");
String passwd = sc.next();
removeArticle(register, passwd);
}
public void removeArticle(String register, String passwd) {
if (boardList.size() > 0) {
int flag = -1;
// 입력한 값이 일치하는게 있는지 확인하는 flag 변수
// 일치하는 값이 있으면 그 값 boardList에서 지워진다.
// 지워지면서 flag값이 인덱스 i의 값으로 초기화된다.
// 그런데 i는 인덱스 값으로 음수가 될 수 없다.
// 따라서 이중 if문의 모두 조건문에 해당하여 이중 if문 들어가서
// 일치하는 값이 ArrayList에서 지워지고 flag값이 인덱스 i로
// 초기화 되면 flag가 -1이냐 아니냐에 따라 일치하는 값이 있는지
// 없는지를 알 수 있게되는 것이다.
for(int i = 0; i <boardList.size(); i++) {
if(boardList.get(i).equals(register)) {
if(boardList.get(i).equals(passwd)) {
boardList.remove(boardList.get(i));
flag = i;
i--;
// i-- 해주는 이유
// i--이 되고 다시 증감식으로 가서 i++을 해주게되면
// i값은 제자리이다.
// 앞에서 원래 그 i인덱스 공간에 있던 값을 삭제하여
// i인덱스의 다음 인덱스에 있는 값이 i인덱스 공간으로
// 옮겨져온다.
// 따라서 인덱스를 옮겨서 값을 비교할 필요없이
// 다시 그 i인덱스로 값을 비교해보면 된다.
}
}
}
if(flag == -1) {
System.out.println("해당 작성자가 없거나 비밀번호가 일치하지 않습니다.");
return;
}
System.out.println("성공적으로 글이 삭제되었습니다.");
}else {
System.out.println("작성된 글이 존재하지 않습니다.");
}
}
}
import java.util.Scanner;
public class BoardMain {
public static void main(String[] args) {
boolean isStop = false;
Scanner sc = new Scanner(System.in);
BoardSVC boardSVC = new BoardSVC();
do {
System.out.println();
System.out.println("메뉴를 입력 하세요");
System.out.println("1.게시판 글쓰기");
System.out.println("2.글 목록 보기");
System.out.println("3.글 삭제");
System.out.println("4.종료");
String menu = sc.next();
switch (menu) {
case "1":
boardSVC.writeArticle(sc); // 값 입력
break;
case "2":
boardSVC.listArticles(sc); // 입력한 값 출력
break;
case "3":
boardSVC.removeArticle(sc);
break;
case "4":
isStop = true;
}
} while (!isStop);
}
}
[ 5 ] 검색 기능을 강화시킨 컬렉션
1. 이진 트리 구조 (Binary 자료구조)
- 부모 노드와 자식 노드로 구성되어 있다.
: 왼쪽 자식 노드 --> 부모 노드보다 작은 값 / 오른쪽 자식 노드 --> 부모 노드보다 큰 값
- 정렬이 쉽다.
- 올림 차순 : [ 왼쪽 노드 --> 부모 노드 --> 오른쪽 노드 ] 순으로 오름차순 정렬
- 내림 차순 : [ 오른쪽 노드 --> 부모 노드 --> 왼쪽 노드 ] 순으로 내림차순 정렬
2. TreeSet (잘 안쓰임)
- 이진트리(binary tree)를 기반으로 한 Set 컬렉션
- 왼쪽과 오른쪽 자식 노드를 참조하기 위한 두개의 left, right 변수로 구성되어 있다.
- TreeSet의 주요 메서드
- 특정 객체를 찾는 메소드: first(), last(), lower(), higher(), …
- 정렬 메소드: descendingIterator(), descendingSet()
- 범위 검색 메소드: headSet(), tailSet, subSet()
3. TreeMap
- 이진 트리(binary tree) 를 기반으로 한 Map 컬렉션
- 키와 값이 저장된 Map.Entry를 저장
- key값은 중복되지 않으므로 key값을 가지고 값을 저장한다.
- 왼쪽과 오른쪽 자식 노드를 참조하기 위한 두 개의 변수로 구성되어 있다.
- 주요 메서드
- 단일 노드 객체를 찾는 메소드: firstEntry(), lastEntry(), lowerEntry(), higherEntry(), …
- 정렬 메소드: descendingKeySet(), descendingMap()
- 범위 검색 메소드: headMap(), tailMap, subMap()
[ 6 ] LIFO와 FIFO 컬렉션
1. Stack (클래스)
- 특징
- 후입선출(LIFO : Last In First Out) 구조
- 응용 : JVM 스택 메모리
- 주요 메서드
- 기본형
: Stack<E> stack = new Stack <E> ( );
public class Coin {
private int value;
public Coin(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
import java.util.Stack;
public class StackExample {
public static void main(String[] args) {
Stack<Coin> coinBox = new Stack<Coin>();
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() + "원");
}
}
}
2. Queue (인터페이스)
- 특징
- 선입선출(FIFO: First In First Out). 예) 작업 큐, 메시지 큐, ....
- Queue 인터페이스를 구현한 대표적인 클래스는 LinkedList이다. LinkedList는 List 인터 페이스를 구현했기 때문에
List 컬렉션이기도 하다. 따라서 LinkedList 객체를 Queue 인 터페이스 타입으로 변환하여 사용한다.
- 주요 메서드
- 기본형
: Queue<E> queue = new LinkedList<E> ( );
public class Message {
public String command;
public String to;
public Message() {
}
public Message(String command, String to) {
this.command = command;
this.to = to;
}
}
import java.util.LinkedList;
import java.util.Queue;
public class QueueExample {
public static void main(String[] args) {
// Queue 인터페이스 를 구현한 LinkedList 클래스
// 인터페이스 구성멤버 : 상수, 추상메서드, 디폴트메서드, 정적메서드
// Queue<Message> messageQueue = new Queue<Message>(); <- Queue는 인터페이스이므로 이렇게 생성못함
// 따라서 Queue는 Queue로 만드는 것이 아니라 LinkedList로 Queue를 만든다.
Queue<Message> messageQueue = new LinkedList<Message>(); // 인터페이스 = 구현 객체
messageQueue.offer(new Message("sendMail", "홍길동"));
messageQueue.offer(new Message("sendSMS", "신용권"));
messageQueue.offer(new Message("sendKaKaoTalk", "홍두께"));
while(messageQueue.isEmpty()) {
Message message = messageQueue.poll();
switch(message.command) {
case "sendMail":
System.out.println(message.to + "님에게 메일을 보냅니다.");
break;
case "sendSMS":
System.out.println(message.to + "님에게 문자를 보냅니다.");
break;
case "sendKaKaoTalk":
System.out.println(message.to + "님에게 카카오톡을 보냅니다.");
break;
}
}
}
}
[ 7 ] 동기화된 컬렉션
- 비 동기화된 컬렉션을 동기화된 컬렉션으로 래핑
- 아래의 메서드들은 모두 Collections에 있는 정적 메서드 즉, static 메서드이다.
[ 8 ] 병렬 처리를 위한 컬렉션
- 동기화(Synchronized) 컬렉션의 단점
- 하나의 스레드가 요소 처리를 할 때 전체를 잠금하는 현상이 발생한다. 즉, 하나의 스레드가 요소 처리할 때
잠금을 걸어 (Lock을 걸어) 다른 스레드는 걔가 다 끝날때까지 가만히 기다려야한다. --> 너무 비효율적!!
- 컬렉션 요소를 병렬처리하기 위해 제공되는 컬렉션
- ConcurrentHashMap
- 부분(segment) 잠금 사용
- 처리하는 요소가 포함된 부분만 잠금
- 나머지 부분은 다른 스레드가 변경 가능하게 --> 부분 잠금
* 하나의 스레드가 요소 처리를 할때 걔가 사용하고 있는 요소에만 일부 잠금을 하여 다른 스레드가
그 요소 외 다른 요소엔 접근할 수 있도록 하는 것을 의미 *
- ConcurrentLinkedQueue
- 락-프리(lock-free) 알고리즘을 구현한 컬렉션
- 잠금 사용하지 않음
- 여러 개의 스레드가 동시에 접근하더라도 최소한 하나의 스레드가 성공하도록
(안전 하게 요소를 저장하거나 얻도록) 처리
'kh-정보교육원' 카테고리의 다른 글
25, 26, 27, 28일차_배운 내용(나는야 코생아 응애,,) (2) | 2022.12.09 |
---|---|
22일차(2)_배운 내용(어김없이 코생아) (0) | 2022.12.04 |
22일차(1)_배운 내용(어김없이 코생아) (1) | 2022.12.01 |
21일_배운 내용(오늘도 코생아) (0) | 2022.12.01 |