도대체 컬렉션이 무엇이란 말인가!!!!
배열에 대해 공부했다. 배열은 연관된 데이터를 관리하는 수단이었다. 그런데 배열에는 몇 가지 불편한 점이 있는데 그 중의 하나가 배열의 크기를 변경할 수 없다는 것이다. 전체 삭제 후 다시 만들어야 한다는 단점;; 이러한 불편함을 Collection, 컬렉션즈 프레임워크를 사용하면 줄일 수 있다.
[배열과 컬렉션의 차이_생활코딩 참고]
배열의 경우, 크기를 한번 지정하면 크기보다 많은 수의 값을 지정할 수 없다.
하지만 ArrayList의 경우에는 크기를 미리 지정하지 않기 때문에 얼마든지 많은 수의 값을 지정할 수 있다.
ArrayList는 배열과 사용방법이 조금 다르다. 배열의 경우 값의 개수를 구할 때 .length를 사용해했지만 ArrayList는 메소드 size를 사용한다. 또한 특정한 값을 가져올 때 배열은 [인덱스 번호]를 사용했지만 컬렉션은 .get(인덱스 번호)를 사용한다.
※주의사항※
위의 코드는 컴파일 오류가 발생한다. ArrayList의 메소드 add의 입장에서는 인자로 어떤 값이 올지 알 수 없다. 그렇기 때문에 모든 데이터타입의 조상인 Object 형식으로 데이터를 받고 있다. 따라서 ArrayList 내에서 add를 통해서 입력된 값은 Object의 데이터 타입을 가지고 있게 된다. 그렇기 때문에 위의 코드는 아래와 같이 바꿔야 한다.
get의 리턴값을 문자열로 형변환하고 있다. 원래의 데이터 타입이 된 것이다. 하지만 이것도 옛날 방식.. 아래와 같이 제네릭을 사용!
★ 컬렉션 : 여러 개의 데이터를 묶어서 처리하는 것
- Collection(List, Set), Map => Collection, Map이라는 최상위 카테고리가 있고 그 아래에 다양한 컬렉션들이 존재한다.
- 선형, 비선형 데이터 => 클래스
- 선형: ArrayList(배열과 똑같음), Vector, LinkedList
- 비선형: Set(집합의 개념, 중복불가), Map
- List, Set, Queue의 하위 클래스들은 모두 각각의 List, Set, Queue의 인터페이스를 구현하기 때문에 모두 같은 API를 가지고 있다. 클래스의 취지에 따라서 구현방법과 동작방법은 다르지만 공통의 조작방법을 가지고 있는 것이다.
[+생활코딩 참고]
[List와 Set의 차이]: List는 중복을 허용하고, Set은 허용하지 않는다.
메소드 iterator는 인터페이스 collection에 정의되어 있다. 따라서 collection을 구현하고 있는 모든 컬렉션즈 프레임워크는 이 메소드를 구현하고 있음을 보증한다. 메소드 iterator의 호출 결과는 인터페이스 iterator를 구현한 객체를 리턴한다. 인터페이스 iterator는 아래 개의 메소드를 구현하도록 강제하고 있는데 각각의 역할은 아래와 같다.
▶ hasNext : 반복할 데이터가 더 있으면 true, 더 이상 반복할 데이터가 없다면 false를 리턴한다.
▶ next : hasNext가 true라는 것은 next가 리턴할 데이터가 존재한다는 의미이다.
이러한 기능을 조합하면 for문을 이용하는 것과 동일하게 데이터를 순차적으로 처리할 수 있다.
다시 본론! Set과 List의 차이는 Set은 중복을 허용하지 않고 순서가 없지만, List는 중복을 허용하고 저장되는 순서가 유지된다는 것을 알 수 있다. 이러한 특징을 고려해서 컬렉션을 선택해야 한다.
▶ ArrayList:
- 일반 배열과 달리 ArrayList는 데이터 삽입, 삭제시 자바 가상머신이 자동으로 처리한다.
- 하지만 삽입, 삭제로 앞, 뒤로 한칸씩 이동하는 것이 부담스러울 수 있기 때문에 삽입, 삭제가 빈번하게 일어날 경우 사용하기 좋지 않다.
- 데이테 추가시 좋음! 조회시 1개의 데이터 good!
- 객체만 집어넣을 수 있다.
▶ LinkedList :
- 1, 2번 데이터의 주소값을 가지고 있어 서로 서로 위치값을 가지고 있다. 다음에 오는 배열의 위치값이 추가되기때문에 Memory가 추가적으로 필요하지만 주소값만 바꿔주면 되기때문에 좋다.
- 데이터를 추가하는 것에 대해서는 ArrayList가 낫지만 삽입, 삭제가 빈번한 경우에는 LinkedList가 더 좋다! (주소값) 링크를 걸어주는 작업은 자바가상머신이 알아서 해준다.
★ 선형
- Stack(선입후출, FILO: First In, Last Out) 예기치못한 상황에서 정보를 저장하는 경우, 운영체제에서 많이 사용함, 함수 호출
- Queue(큐)(FIFO, FIFS) ex) 프린트기, 인쇄대기열
내가 자꾸 실수하는 것!
ArrayList, Set, Map를 사용하기 위해선 public static void main(String[] args)이 있어야 한다.
ArrayList<Integer>
<ArrayList의 데이터 삽입 add>
<ArrayList의 get, 데이터를 꺼낼 때>
List<Integer> list2 = new ArrayList<>();
list2.add(new Integer(10));
→ 전달인자로 하나만 넣으면 계속 뒤로 추가가 되는 것!
[FriendVO] : 한 사람의 데이터를 저장할 수 있는 객체 타입
여러 사람의 데이터를 저장하고 싶다면? ArrayList
ArrayListTest2는 FriendVO를 담는 객체!
ArrayListTest2는 FriendVO를 저장할 ArrayList가 필요!
<ArrayList의 CRUD>
주의 java.util 선택! (java.awt 아님)
<ArrayList의 데이터 삽입 add>
여러 사람의 데이터를 넣을 수 있는 ArrayList를 만들어 한 사람의 데이터만 넣을 수 있는 FriendVO의 메소드를 이용
list.add(new FriendVO("저팔계", 88));
위에서 하나의 객체를 의미하는 것은 new FriendVO("저팔계", 88);이다.
▷ Index를 이용해 객체의 위치, 주소에 변화를 주고 싶다면?
▶ ArrayList <>안에는 객체만 집어넣을 수 있다.
ArrayList<String> list1 = new ArrayList<>();
List<Integer> list2 = new ArrayList<>();
List<FriendVO> list = new ArrayList<>();
▶ 일반 for문과 다른 업그레이드 버전의 for문
for(FriendVO vo: list)
System.out.println(vo);
: 객체 FriendVO의 list(전체 데이터)를 하나씩 꺼내어 vo에 담은 다음에 꺼내어 출력
<ArrayList의 전체데이터 출력(순회)>
<ArrayList의 데이터 위치(index)를 이용해 꺼내기 get>
<ArrayList의 데이터 값을 이용해 꺼내기 get>
코드 압축 전
데이터 조회시, 데이터의 값을 알고 있을 경우, 전체 데이터를 돌려 찾고자 하는 데이터와 같은지 불러와야 한다. 열어보기 ↓
for(int i =0; i < list.size(); ++i) {
FriendVO tmp = list.get(i);
if(tmp.getName().equals("사오정"))
System.out.println(tmp);
}
: for문을 돌려 ArrayList의 크기만큼 반복하고 한 사람의 정보를 의미하는 FriendVO의 변수명 tmp는 list.get(i);를 통해 값을 불러온다. 그렇게 불러온 각각의 데이터의 이름을 불러와 내가 찾고자 하는 값과 내용이 같은지 비교한 후 if문을 이용해 같다면 출력하면 된다.
코드 압축 후
list.get(i)를 출력하면 list.get(i)의 정보가 나오고
list.get(i).getName() 이렇게 출력하면 이름만 나온다.
전체 데이터를 조회하는 Full Scan(좋지 않다)를 사용하기엔 실무에선 데이터의 수가 셀 수없이 많기때문에 조회하는 retrieve 메소드를 잘 만들어 놓는 것이 중요하다. 이름을 찾을 일이 많다고 하면 이름을 정렬해서 빨리 검색, 찾을 수 있게 해둔다.
[Full Scan] : 데이터 전체를 조회
[binary search]
: (데이터 5000만개 중 절반만 검색) 검색의 데이터의 양을 줄여나감
: Up&Down 게임을 생각하면 좋다.
: 정렬이 되어 있는 상태에서만 사용할 수 있다.
<ArrayList의 데이터 삭제 remove>
삭제한다는 것은 즉 그 안의 데이터를 꺼내야 한다는 것을 의미!
데이터를 조회해 찾아 삭제 후 전체 출력, 손오공의 데이터가 삭제되었음을 알 수 있다.
(내 실수) 찾을려고 했던 데이터가 틀렸을 때
"손오공"을 찾아야 하는데 "손온공"
왜 (list.remove(i) == null)이 "삭제 실패"이지? "삭제 성공"아닌가?
삭제해서 튀어나온 값이 null이라면?
이것은 객체이기 때문에 null이냐 아니냐로 알 수 있는데, 그렇다면 객체의 기본값은 null이기 때문에 null이라면 삭제 실패인 것이다.
[2교시]
<ArrayList의 데이터 수정 get, set>
홍길동 나이 수정
홍길동의 나이가 수정된 것을 확인할 수 있다.
[Set]
: 한국어로 집합이라는 뜻이다. 여기서의 집합이란 수학의 집합과 같은 의미이다. 수학에서도 집합의 순서가 없고 중복되지 않는 특성이 있다. 수학에서 집합은 교집합, 차집합, 합집합과 같은 연산을 할 수 있고 Set에서도 마찬가지이다.
많이 사용하지 않기 때문에 이런 게 있구나~하고만 알아두기
: set은 집합의 개념으로 중복 불가! 중복을 허용하지 않는다.
: N번방 개념이 없다.
get처럼 명확하게 꺼내오는 것은 없다.
<Set의 데이터 삽입 add>
set은 집합의 개념으로 중복된 데이터를 허용하지 않는다.
<Set의 강제로 전체순회 Iterator>
Iterator는 정렬을 도와주는 함수
Iterator<E> 안에 들어갈 수 있는 타입은?
Iterator<String> iter = set.iterator();
→ set.iterator(); : 데이터를 순회할 수 있는 객체를 달라
→ Iterator<String> iter : 데이터를 순회할 수 있는 객체를 전달해줌
→ iter를 통해 전체 데이터를 순회할 수 있다.
Iterator는 순회가 목적이기 때문에 몇 번 순회를 해야하는 지 모른다!
hasNext(); : 다음 데이터가 있니? 꺼낼 데이터가 있으면 True, 아니면 False, 데이터가 있는 만큼 움직이고 더 이상 다음에 올 데이터가 없다면 더 이상 꺼낼 데이터가 없다는 의미의 False
while(iter.hasNext()); : 꺼낼 데이터가 있니?
next() : 다음 데이터를 꺼내시오!
Iterator<String> iter = set.iterator();
while(iter.hasNext()){
System.out.println(iter.next());
}
데이터의 순서는 제맘대로! 순서대로 조회되지 않는다.
[Set의 집합]
▶ hasNext : 반복할 데이터가 더 있으면 true, 더 이상 반복할 데이터가 없다면 false를 리턴한다.
▶ next : hasNext가 true라는 것은 next가 리턴할 데이터가 존재한다는 의미이다.
[Map]
: Key와 Vaule의 쌍으로 값을 저장하는 컬렉션이다.
: List와 Set과 다르게 Collection에서 상속 받은 것은 아니지만 인터페이스이다.
배우기 전에 Map 맛보기!
Map에서 데이터를 추가할 때 사용하는 API는 put이다. put의 첫번째 인자는 값의 key이고, 두번째 인자는 key에 대한 값이다. Key를 이이용해서 값을 가져올 수 있다.
Map에 저장된 데이터를 열거할 때는 아래와 같이 한다.
메소드 entrySet은 Map의 데이터를 담고 있는 Set을 반환한다. 반환한 Set의 값이 사용할 데이터 타입은 Map.Entry이다. Map.Entry는 인터페이스인데 아래와 같은 API를 가지고 있다. API를 이용해 Map의 key, value를 조회할 수 있다.
▶ getKey
▶ getValue
앞서 공부한 Set이 수학의 집합을 프로그래밍적으로 구현한 것이라면 Map은 수학의 함수를 프로그래밍화한 것이다.
[데이터 타입의 교체]
: 컬렉션을 사용할 때는 데이터 타입을 가급적 해당 컬렉션을 대표하는 인터페이스를 사용하는 것이 좋다.
HashMap은 Map 인터페이스를 구현하기 때문에 변수 a의 데이터 타입으로 Map을 사용할 수 있다.
HashMap<String, Integer> a = new HashMap<>();
=> Map<String, Integer> a = new HashMap<>();
필요에 의해 컬렉션을 HashMap에서 HashTable로 바꾸고 싶다면 아래와 같이 수정하면 된다.
=> Map<String, Integer> a = new HashTable<>();
Map은 ArrayList만큼 중요함
map 자료는 엑셀의 표에 비교해 데이터가 들어간다고 생각하면 good! 하지만 순서가 없다.
저장된 정보(객체, 값)이 있다하면 Key를 통해 데이터를 찾음
Key(Primary Key)는 유일해야 하고 객체를 찾아낼 수 있어야 한다.
ex) Key는 학교에서 학번의 의미함.
Map<Integer, String> map = new HashMap<Integer, String>();
Map<Integer, String> map = new HashMap<>(); <-이렇게 써도 됨
→ Integer, String 여기를 생략해도 된다는 의미, 키로 Integer, 값으로 String
Nested 내부 인터페이스 : Map 안에 인터페이스
Map ⊃ Map.Entry
put(K Key, V value)은 특정 키와 함께 데이터 값을 넣을 수 있음. 데이터 삽입
get(Object key)은 특정 키의 값을 리턴(Map은 방이 없어 순서, index가 없어 key로만) 데이터 조회
Map<Integer, String> map = new HashMap<>();
Map에는 Index가 없기 때문에 map.put(1, "홍길동); ← 앞에 있는 번호가 학번과 같은 유일한 Key
<Map의 데이터 삽입 put>
<Map의 데이터 찾기 get>
<Map의 데이터 수정 put>
데이터를 삽입할 때 사용했던 put()를 이용해 기존에 있는 데이터를 날려버리고 데이터를 넣음 = Update
<Map의 데이터 삭제 remove>
값이 아직 넣어지지 않은 (Key 7)의 값을 지우려고 하면 null 값이 출력된다.
Key 5를 가진 윤장군은 map.put(5, "윤장군")이 사라졌기 때문에 null으로 나오는 것이다.
[3교시]
[HashMap()]
Constructs an empty HashMap with the default initial capacity (16) and the default load factor (0.75).
전체 16개 중에 메모리(load factor)가 75% 찼을 때
key값만 가져옴
value값만 가져옴
<HashMap의 CURD>
삭제가 안되면 null이 출력됨
replace, put을 가지고 데이터 수정
get을 가지고 데이터 조회
<HashMap의 전체순회>
Key의 값만 가져오는 Set<K> KeySet(); → Set<Integer> keys = map.keySet();
Map의 경우, 순서가 없기 때문에 Set<K> KeySet();를 이용해 정렬 후 Iterator를 가지고 순회한다.
코드 압축 전,
Set<Integer> keys = map.keySet();
Iterator<Integer> iter = keys.iterator();
코드 압축 후,
Iterator<Integer> iter = map.keySet().iterator();
[HashMap(int initialCapacity)]
Constructs an empty HashMap with the specified initial capacity and the default load factor (0.75).
(적재 데이터의 크기, 로드)
Map<Integer, String> map2 = new HashMap<>(30, 0.6F);
Map<Integer, String> map = new HashMap<>(); <= 보통은 이렇게 사용
[FitenessService 수정]
객체배열인 Fitness[] list = new FitnessVO[3], int count = 0; 이렇게 썼지만 ArrayList를 쓰면 이 작업이 필요없어진다. (삭제해주세요)
ArrayList의 객체는 FitnessVO!
▷ 회원가입 수정 전
더 이상 count가 없기때문에 지워주고, 회원이 없는 경우는 ArrayList의 list의 size가 0이면 회원이 없는 것이다.
if(list.size() ==0) {
System.out.println("*** 회원 가입을 할 수 없습니다. ");
return;
}
↑ 이런식으로 코드를 넣을 수도 있지만 이제는 회원수 제한이 없는 것이기 때문에 코드가 필요 없다.
▷ 회원가입 수정 후
ArrayList에서는 데이터를 삽입할 때, add라는 것 잊지말기
list.add(new FitnessVO(userid, name, height, weight));
map으로 바꾼다면 "//기존에 입력된 데이터 중 동일 아이디가 있는지 확인" 작업에서 for문이 필요없다. map은 key가 유일하기 때문이다.
▷ 조회 수정 전
▷ 조회 수정 후
▷ 회원정보 수정 전
▷ 회원정보 수정 후
▷ 회원정보 삭제 전
▷ 회원정보 삭제 후
answer가 "Y"이면 list.remove(i)
list[j] = list[j+1]; ← 뒤의 값을 하나씩 땡겨올 용도로 사용되던 코드가 더 이사 필요 없어지고 for문도 필요없어짐.
▷ 전체출력 수정 전
▷ 전체출력 수정 후
[파일 압축 방법]
Export - General - Archive File
-.class.path
-.project
모두 선택 후 파일 저장할 곳(browse)
[주말과제]
위의 Fitnessservice에서 Arraylist를 HashMap으로 바꿔보기
Fitness V3를 V4로 바꿔보기
'개발자로 가는 길(국비지원과정) > 1. Java' 카테고리의 다른 글
[210510월] Collection, ArrayList 복습, 코딩 연습 (0) | 2021.05.10 |
---|---|
[과제] 코드 Fitness(배열 전) (0) | 2021.05.09 |
[210506목] Wrapper class, Exception (0) | 2021.05.06 |
[210504화] 다형성, 추상메소드, 인터페이스 (0) | 2021.05.04 |
[7주차질문] (0) | 2021.05.03 |