고래씌
[JAVA] 14-1. 컬렉션(Collection) - ArrayList 본문
1. 컬렉션(Collection)
: 자료구조가 내장되어있는 클래스로 자바에서 제공하는 "자료구조"를 담당하는 "프레임워크"
▶ 자료구조 : 방대한 데이터들을 효율적으로 다룰때 필요한 개념을 클래스로 정의한 것
▶ 프레임워크 : 효율적인 기능들이 이미 정의되어 있는 틀
☞ 데이터들이 새롭게 추가되거나, 삭제가 되거나, 수정이 되는 기능들이 이미 정의되어있는 틀이 있다 == 컬렉션
☞ 다량의 데이터들을 관리하고자 할 때 배열 가지고 충분히 사용을 할 수 있었지만, 배열이 가진 단점들을 보완한 것이 컬렉션
1) 배열과 컬렉션의 차이점
- 배열의 단점
① 배열을 쓰고자 할 때 먼저 크기를 지정해야함. 한번 지정된 크기는 변경이 불가
만약, 새로운 값을 추가하고자 한다면 크기가 오버될 경우 새로운 크기의 배열을 만들고 기존의 내용들을 복사해서 옮겨주는 코드를 직접짜야 했음
② 배열 중간 위치에 새로운 데이터를 추가하거나, 삭제하는 경우 기존의 값들을 땡겨주는 코드를 직접 짜줘야함.
③ 한 타입의 데이터들만 저장 가능
- 컬렉션의 장점
① 크기에 제약이 없다.
=> 크기 지정을 해줄 필요도 없고, 만일 같은 크기지정을 해도 알아서 크기가 늘어나거나 줄어드는 코드가 내부적으로 이미 정의되어 있음
② 중간에 값을 추가하거나 삭제하는 경우 값들을 땡겨주는 코드가 이미 내부적으로 정의되어 있음
③ 여러타입의 데이터들을 저장할 수 있음(단, 제네릭설정을 통해 한 타입의 데이터들만 들어올 수 있게끔도 가능)
▶ 배열 --> 방대한 데이터들을 단지 담아만 두고 조회만 할 목적이다.
▶ 컬렉션 --> 방대한 데이터들이 빈번하게 추가, 삭제, 수정이 될 것 같다.
2) 컬렉션의 3가지 분류
▶ List 계열
① 담고자하는 값(value)만 저장하는 자료구조
② 값을 저장할 때 순서가 유지됨(즉, index 개념 有)
③ 중복값을 허용함
- List계열 자식 클래스 : ArrayList, Vector, LinkedList => ArrayList가 자주 쓰임
▶ Set 계열
① 담고자하는 값(value)만 저장하는 자료구조
② 값을 저장할 때 순서를 유지하지 않음(index 개념 無)
③ 중복값을 허용하지 않음
- Set계열 자식 클래스 : HashSet, TreeSet
▶ Map 계열
① 담고자하는 값(value)을 키(key)에다가 저장
② 값 저장시 순서를 유지하지 않음(index 개념 無)
③ value 값을 중복을 허용하나, key값은 중복을 허용하지 않음
- Map계열 자식 클래스 : HashMap, HashTable, Properties
2. 제네릭(Generics)
: 제네릭(<E>)
별도의 제네릭 제시 없이 컬렉션 객체를 생성하면, 해당 컬렉션에는 다양한 타입의 데이터 값들이 담길 수 있음.
ex) List<Music> list = new ArrayList<Music>(3);
☞ 별도의 제네릭 설정으로 <Music>으로 하게되면 해당 컬렉션에는 Music객체만 담을 수 있음
1) 제네릭을 설정하는 이유
① 명시한 타입의 객체만 저장가능하도록 타입의 제한을 두기 위해서 --> 안전성 확보 가능
② 컬렉션에 저장된 객체를 꺼내서 사용할 때 매번 형변환해야하는 절차를 없애기 위해서
3. List 계열(ArrayList)
1) add(E e) : 해당 리스트의 끝에 전달된 e를 추가시켜주는 메소드
=> 순차적으로 추가됨
List list = new ArrayList(); // 내부적으로 크기 10짜리인 배열이 생성
=> 여러 다양한 자료형을 저장할 수 있음
List<Music> list = new ArrayLIst<Music>(3) // Music 타입의 객체만 들어올 수 있음. 제네릭을 사용하였기 때문에.
=> 배열이 3짜리인 배열 생성
package com.kh.chap01_list.part01_arrayList.model.vo;
public class Music {
private String title;
private String artist;
public Music() {
}
public Music(String title, String artist) {
super();
this.title = title;
this.artist = artist;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
@Override
public String toString() {
return "Music [title=" + title + ", artist=" + artist + "]";
}
}
package com.kh.chap01_list.part01_arrayList.run;
import java.util.ArrayList;
import java.util.List;
import com.kh.chap01_list.part01_arrayList.model.vo.Music;
public class Run {
public static void main(String[] args) {
List<Music> list = new ArrayList<Music>(3); // Music 타입의 객체만 들어올 수 있음
// System.out.println(list); // 안에 아무것도 없는 상태(비어있음) + toString오버라이딩 되어 있음
// 1. add(E e) : 해당 리스트의 끝에 전달된 e를 추가시켜주는 메소드
list.add(new Music("ditto","뉴진스"));
list.add(new Music("ETA","뉴진스"));
list.add(new Music("hype boy", "뉴진스"));
list.add(new Music("고백","장범준"));
System.out.println(list);
}
}
☞ 순서가 유지되면서 값이 추가됨
☞ 크기에 제약이 없음
☞ 제네릭 설정을 하지 않는다면, 다양한 타입의 값 추가 가능
2) add(int index, E e) : 리스트에 전달되는 index값 위치에 전달되는 e를 추가시켜주는 메소드
: 중간에 값 추가시 알아서 기존의 값들을 뒤로 땡겨주는 작업이 내부적으로 진행됨
package com.kh.chap01_list.part01_arrayList.run;
import java.util.ArrayList;
import java.util.List;
import com.kh.chap01_list.part01_arrayList.model.vo.Music;
public class Run {
public static void main(String[] args) {
List<Music> list = new ArrayList<Music>(3); // Music 타입의 객체만 들어올 수 있음
// 1. add(E e) : 해당 리스트의 끝에 전달된 e를 추가시켜주는 메소드
list.add(new Music("ditto","뉴진스"));
list.add(new Music("ETA","뉴진스"));
list.add(new Music("hype boy", "뉴진스"));
list.add(new Music("고백","장범준"));
System.out.println(list);
// 2. add(int index, E e) : 리스트에 전달되는 index값 위치에 전달되는 e를 추가시켜주는 메소드
list.add(1, new Music("this love", "빅뱅")); // list[1] = new Music("?","?")
System.out.println(list);
}
}
3) set(int index, E e) : 리스트에 해당 인덱스 값을 전달되는 e로 변경시켜주는 메소드
package com.kh.chap01_list.part01_arrayList.run;
import java.util.ArrayList;
import java.util.List;
import com.kh.chap01_list.part01_arrayList.model.vo.Music;
public class Run {
public static void main(String[] args) {
List<Music> list = new ArrayList<Music>(3); // Music 타입의 객체만 들어올 수 있음
// 1. add(E e) : 해당 리스트의 끝에 전달된 e를 추가시켜주는 메소드
list.add(new Music("ditto","뉴진스"));
list.add(new Music("ETA","뉴진스"));
list.add(new Music("hype boy", "뉴진스"));
list.add(new Music("고백","장범준"));
System.out.println(list);
// 2. add(int index, E e) : 리스트에 전달되는 index값 위치에 전달되는 e를 추가시켜주는 메소드
list.add(1, new Music("this love", "빅뱅")); // list[1] = new Music("?","?")
// 중간에 값 추가시 알아서 기존의 값들을 뒤로 땡겨주는 작업이 내부적으로 진행됨
System.out.println(list);
// 3. set(int index, E e) : 리스트에 해당 인덱스 값을 전달되는 e로 변경시켜주는 메소드
list.set(1, new Music("바다의 왕자","박명수")); // list[1] = new Music("?","?")
System.out.println(list);
}
}
☞ list.set(1, new Music("바다의 왕자","박명수"));
=> 1번 인덱스의 값이 변경된 것을 확인
4) remove(int index) : 리스트에 해당 인덱스의 값을 삭제시켜주는 메소드
ex) list.remove(1);
=> 1번 인덱스에 있는 것을 삭제하고 뒤쪽에 있던 인덱스를 앞으로 옮김
package com.kh.chap01_list.part01_arrayList.run;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.kh.chap01_list.part01_arrayList.model.vo.Music;
public class Run {
public static void main(String[] args) {
List<Music> list = new ArrayList<Music>(3); // Music 타입의 객체만 들어올 수 있음
// 1. add(E e) : 해당 리스트의 끝에 전달된 e를 추가시켜주는 메소드
list.add(new Music("ditto","뉴진스"));
list.add(new Music("ETA","뉴진스"));
list.add(new Music("hype boy", "뉴진스"));
list.add(new Music("고백","장범준"));
System.out.println(list);
// 2. add(int index, E e) : 리스트에 전달되는 index값 위치에 전달되는 e를 추가시켜주는 메소드
list.add(1, new Music("this love", "빅뱅")); // list[1] = new Music("?","?")
System.out.println(list);
// 3. set(int index, E e) : 리스트에 해당 인덱스 값을 전달되는 e로 변경시켜주는 메소드
list.set(1, new Music("바다의 왕자","박명수")); // list[1] = new Music("?","?")
System.out.println(list);
// 4. remove(int index) : 리스트에 해당 인덱스의 값을 삭제시켜주는 메소드
list.remove(1);
System.out.println(list);
}
}
=> 1번 인덱스 삭제됨
5) size() : 리스트에 담겨있는 데이터의 수를 반환해주는 메소드
System.out.println("리스트에 담긴 데이터 수 : " + list.size());
System.out.println("리스트에 마지막 인덱스 : " + (list.size()-1));
6) get(int index) : E => 리스트에 해당 index위치의 데이터를 반환해주는 메소드
Music m = list.get(1); // 데이터를 반환할때도 Music 객체만 반환. 자료형이 일치하기 때문에 에러발생 X
System.out.println(list.get(1));
System.out.println(list.get(1).getTitle()); // 제목만 가져올수 있음
※ ★만약 제너릭을 안하고 List list = new ArrayList(); 를 선언해주었다면?
Music m = list.get(1);
System.out.println(list.get(1).getTitle());
☞ 모두 에러 발생. 다양한 자료형을 꺼내올 수 있어서 이때는 직접 강제형변환을 해주어야 한다!
↓↓
Music m = (Music) list.get(1);
System.out.println( ((Music)list.get(1)).getTitle());
☞ 에러 발생 X
package com.kh.chap01_list.part01_arrayList.run;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.kh.chap01_list.part01_arrayList.model.vo.Music;
public class Run {
public static void main(String[] args) {
List<Music> list = new ArrayList<Music>(3); // Music 타입의 객체만 들어올 수 있음
// 1. add(E e) : 해당 리스트의 끝에 전달된 e를 추가시켜주는 메소드
list.add(new Music("ditto","뉴진스"));
list.add(new Music("ETA","뉴진스"));
list.add(new Music("hype boy", "뉴진스"));
list.add(new Music("고백","장범준"));
System.out.println(list);
// 2. add(int index, E e) : 리스트에 전달되는 index값 위치에 전달되는 e를 추가시켜주는 메소드
list.add(1, new Music("this love", "빅뱅")); // list[1] = new Music("?","?")
// 3. set(int index, E e) : 리스트에 해당 인덱스 값을 전달되는 e로 변경시켜주는 메소드
list.set(1, new Music("바다의 왕자","박명수")); // list[1] = new Music("?","?")
// 4. remove(int index) : 리스트에 해당 인덱스의 값을 삭제시켜주는 메소드
list.remove(1);
// 1번 인덱스에 있는 것을 삭제하고 뒤쪽에 있던 인덱스를 앞으로 옮김
// 6. get(int index) : E => 리스트에 해당 index위치의 데이터를 반환해주는 메소드
Music m = list.get(1); // 데이터를 반환할때도 Music 객체만 반환. 자료형이 일치하기 때문에 에러발생 X
System.out.println(list.get(1));
System.out.println(list.get(1).getTitle()); // 제목만 가져올수 있음
}
}
7) contains(E e) : boolean => 매개변수로 넘어온 값이 현재 컬렉션에 포함되어있는지 확인
ArrayList<Integer> Iarr = new ArrayList<>(3); // java7버전부터 추가된 내용. 뒤에 <같은 자료형>을 작성하지 않아도 작동됨
Iarr.add(1);
Iarr.add(9);
Iarr.add(900);
System.out.println(Iarr.contains(90));
8) indexOf(E e) : int => 매개변수로 넘어온 값이 현재 컬렉션에 몇번째 인덱스에 존재하는지 반환 / 없다면 -1을 반환
ArrayList<Integer> Iarr = new ArrayList<>(3);
Iarr.add(1);
Iarr.add(9);
Iarr.add(900);
System.out.println(Iarr.indexOf(9000));
=> -1 반환
▶ 베이직 for문
- 0번 인덱스 ~ 마지막 인덱스까지의 데이터 출력
for(int i=0; i<list.size(); i++) {
System.out.println(list.get(i));
}
▶ 향상된 반복문 : for each문
- for( 값을 받아줄 변수 : 순차적으로 접근할 배열 또는 컬렉션)
- 제네릭 설정 전(강제형변환 필요)
for( Object o : list ) {
}
- 제네릭 설정 후
for(Music o : list) {
System.out.println(o);
}
※ Iterator 반복자
: 컬렉션 내부 인자들을 Iterator에 담아서 관리(String의 StringTokenzier 비슷함)
Iterator<Music> iter = list.iterator(); // 컬렉션을 iterator 객체로 변환
while(iter.hasNext()) {
Music music = iter.next(); // next함수가 호출되었을때 다음 한칸으로 이동
System.out.println(music);
}
9) subList(int index1, int index2) : 해당 리스트로부터 index1에서부터 index2까지의 데이터 값들을 추출해서 새로운 List로 반환시켜주는 메소드
☞ list.subList(0, 2) ==> 0 <== 인덱스 < 2
List<Music> sub = list.subList(0, 2);
System.out.println(sub);
10) addAll(Collection c) : 해당 리스트에 다른 컬렉션에 있는 데이터들을 통째로 추가해주는 메소드
list.addAll(sub);
System.out.println(list); // Collection 은 List,와 set의 부모(조상)임
11) isEmpty() : 해당 리스트가 비어있는지 묻는 메소드(비어있으면 true / 비어있지 않으면 false 반환)
12) clear() : 해당 리스트를 싹 비워주는 메소드
// 11. isEmpty() : 해당 리스트가 비어있는지 묻는 메소드(비어있으면 true / 비어있지 않으면 false 반환)
System.out.println("리스트가 비어있습니까? " + list.isEmpty());
// 12. clear() : 해당 리스트를 싹 비워주는 메소드
list.clear();
System.out.println("리스트가 비어있습니가? " + list.isEmpty());
13) sort(List list) : 컬렉션 내부의 값들을 정렬시켜주는 함수
내가 직접 정의한 객체를 정렬하기 위해서는 "정렬기준"을 새롭게 만들어줘야함
▶ 객체 정렬방법 2가지
① Comparable 인터페이스 구현
기본 정렬(한가지 방법만 가능)을 클래스에서 구현
정렬시 사용하는 compareTo메소드를 오버라이딩 하는 방식
→ 정렬기준을 한가지만 세울수 있음
② Comparator 인터페이스
객체의 기본정렬 외에 추가적으로 여러개의 정렬기준을 제시하고자 할 때 사용.
ex) 가수이름 오름차순 정렬, 내림차순 정렬, 음악제목 오름차순, 내림차순 정렬을 각각 만들고 싶을때 별도의 Comparator구현 클래스를 작성하면 된다.
compare 메소드 오버라이딩
☞ Comparable은 자기 자신과 파라미터로 들어오는 객체를 비교하는 것
☞ Comparator는 파라미터로 들어오는 두 객체를 비교하는 것
■ Comparable
- 반환값
동등 : 0
현재객체가 더 높음 : 1
상대객체가 더 높음 : -1
package com.kh.chap01_list.part01_arrayList.model.vo;
public class Music implements Comparable<Music>{
private String title;
private String artist;
public Music() {
}
public Music(String title, String artist) {
super();
this.title = title;
this.artist = artist;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
@Override
public String toString() {
return "Music [title=" + title + ", artist=" + artist + "]";
}
@Override
public int compareTo(Music o) {
// 매개변수의 Music객체는 현재객체와 비교하고자하는 객체
// 현재객체 : this
// 상대객체 : Music o
// 반환값이 0 : 동등, 1: 현재객체 더 높다, -1 : 상대객체가 더 높다
// artist 기준 오름차순 정렬
return this.artist.compareTo(o.artist);
}
}
☞ Music 클래스에 public class Music implements Comparable<Music> 를 추가해주면 자동으로 compartTo 메소드가 추가됨.
// 1번 Comparable 기본정렬 : 가수이름 오름차순
Collections.sort(list);
System.out.println(list);
// 가수이름 내림차순
Collections.sort(list, Collections.reverseOrder());
System.out.println(list);
☞ 정렬된 것을 확인
■ Comparator 정렬
별도의 Comparator구현 클래스를 작성후 compare 메소드 오버라이딩
package com.kh.chap01_list.part01_arrayList.model.vo;
import java.util.Comparator;
public class MusicTitleAscendingCompartor implements Comparator<Music>{
// 제목기준 오름차순
@Override
public int compare(Music o1, Music o2) {
return o1.getTitle().compareTo(o2.getTitle());
}
}
Comparator<Music> comp2 = new MusicTitleAscendingCompartor().reversed(); // reversed 역순
Collections.sort(list, comp2);
System.out.println(list);
Q. 반복문을 통해 컬렉션에 담긴 요소를 체크한 후 삭제하기
ArrayList<Integer> list2 = new ArrayList<>();
list2.add(1);
list2.add(1);
list2.add(1);
list2.add(3);
list2.add(4);
list2.add(5);
- 방법 ①
// 삭제완료 후 컬렉션에 저장된 데이터 출력
for(int i=0; i<list2.size(); i++) {
if(list2.get(i) == 1) {
list2.remove(i); // 삭제되는 순간 list의 사이즈가 1 작아져서 바로 다음에 오는 객체를 검사하지 못함.
i--; // 이걸로 해결이 가능하다
}
}
-방법 ②
// 가장좋은 방법 == Iterator 사용
Iterator<Integer> iter2 = list2.iterator();
while(iter2.hasNext()) {
int s = iter2.next();
if(s == 1) iter2.remove(); // 현재 참조하고 있는 collection 요소를 제거
}
14) Collections.shuffle(List list); 배열 랜덤으로 섞기
ArrayList<Integer> list2 = new ArrayList<>();
list2.add(1);
list2.add(1);
list2.add(1);
list2.add(3);
list2.add(4);
list2.add(5);
Iterator<Integer> iter2 = list2.iterator();
while(iter2.hasNext()) {
int s = iter2.next();
if(s == 1) iter2.remove(); // 현재 참조하고 있는 collection 요소를 제거
}
Collections.shuffle(list2);
System.out.println(list2);
System.out.println("======================");
15) 연산자 비교
list.get(2) == smaple ==> 피드에 초기화된 값이 동일해도 주소값은 다르기 때문에 'false'출력
list.get(2).equals(sample)) => 필드에 초기화된 값이 동일할 경우 같은 객체로 인식하기 때문에 'true'출력
// equals 메소드 오버라이딩 후 Music 객체 비교
System.out.println(list.get(2));
// == 연산자를 이용한 비교
Music sample = new Music("ditto", "뉴진스");
System.out.println(sample);
System.out.println(list.get(2) == sample); // 주소값은 다름
System.out.println(list.get(2).equals(sample)); // 필드에 초기화된 값이 동일할 경우 같은 객체로 인식
16) Object o가 Music타입인지 타입검사 및 hashCode()
- 두 객체간에 필드값이 동일하다면 같은 객체로 인식할 수 있도록 override를 함
- equals 메소드를 오버라이딩한다면 항상 hashCode도 함께 오버라이딩해줘야함
두 객체간에 equals결과가 true라면(같은 필드값을 가지고 있다면), hashCode로 반환된 값도 동일해야함
package com.kh.chap01_list.part01_arrayList.model.vo;
import java.util.Objects;
public class Music implements Comparable<Music>{
private String title;
private String artist;
public Music() {
}
public Music(String title, String artist) {
super();
this.title = title;
this.artist = artist;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
@Override
public String toString() {
return "Music [title=" + title + ", artist=" + artist + "]";
}
/*
* equals에서 사용한 필드들을 똑같이 이용하여 hashCode를 생성해줘야함.
*/
@Override
public int hashCode() {
return Objects.hash(title, artist);
}
/*
* 두 객체간에 필드값이 동일하다면 같은 객체로 인식할 수 있도록 override를 함
*
* equals 메소드를 오버라이딩한다면 항상 hashCode도 함께 오버라이딩해줘야함
* 두 객체간에 equals결과가 true라면(같은 필드값을 가지고 있다면), hashCode로 반환된 값도 동일해야함
*/
@Override
public boolean equals(Object o) {
// Object o가 Music타입인지 타입검사
if(!(o instanceof Music)) {
return false;
}
Music other = (Music) o; // 다른 자료형의 객체가 넘어왔다면 형변환 에러가 발생하기 때문
if(!this.title.equals(other.title)) {
return false;
}
if(!this.artist.equals(other.artist)) {
return false;
}
return true;
// 현재객체 : this
// 상대객체 : Object o
}
@Override
public int compareTo(Music o) {
// 매개변수의 Music객체는 현재객체와 비교하고자하는 객체
// 현재객체 : this
// 상대객체 : Music o
// 반환값이 0 : 동등, 1: 현재객체 더 높다, -1 : 상대객체가 더 높다
// artist 기준 오름차순 정렬
return this.artist.compareTo(o.artist);
}
}
'JAVA > JAVA 기초' 카테고리의 다른 글
[JAVA] 14-2. 컬렉션(Collection) - Set (0) | 2023.10.25 |
---|---|
[JAVA] ArrayList - Music 실습 문제 (0) | 2023.10.24 |
[JAVA] 입출력(보조스트림) 실습문제 (0) | 2023.10.24 |
[JAVA] 13-3. 입출력(IO) (보조스트림) (0) | 2023.10.23 |
[JAVA] 입출력 실습문제 (0) | 2023.10.23 |