▶ 컬렉션(Collection)
- 자료구조가 내장되어 있는 클래스로 자바에서 제공하는 "자료구조"를 담당하는 "프레임워크"이다.
- 다량의 데이터들을 관리하고자 할 때 배열 가지고 충분히 사용가능했었다. 단, 배열의 단점을 보완한 것이 컬렉션이다.
- 데이터들이 새로이 추가되거나, 삭제가 되거나, 수정이 되는 기능들(알고리즘)들이 이미 정의되어 있는 틀이 바로 컬렉션이다.
■ 자료구조
- 방대한 데이터를 효율적으로 다룰때 필요한 개념
■ 프레임워크
- 효율적인 기능들이 이미 정의되어있는 틀
■ 배열과 컬렉션의 차이점
● 배열의 단점
1. 배열을 쓰고자 할 때는 먼저 크기를 지정해줘야 한다.
=> 한번 지정한 크기는 변경이 불가하다. 즉, 새로운 값을 추가하고자 할 때 크기가 오버될 경우 새로운 크기의 배열을 만들고 기존의 내용들을 복사해 주는 코드를 직접 짜야한다.
2. 배열 중간 위치에 새로운 데이터를 추가하거나 삭제하는 경우 기존의 값들을 당겨주는 코드도 직접 짜야하다.
3. 한 타입의 데이터들만 저장 가능하다.
● 컬렉션의 장점
1. 크기에 제약이 없다
=> 크기지정을 해줄 필요도 없고 만일 크기지정을 해도 알아서 크기가 늘어나면서 새로운 데이터를 추가해 주는 코드가 이미 정의되어 있다.
2. 중간에 값을 추가하거나 삭제하는 경우 값을 당겨주는 코드가 이미 메서드로 정의되어 있다.
3. 기본적으로 여러 타입의 데이터들을 저장할 수 있다(단, 제네릭 설정을 통해서 한 타입의 데이터들만 들어올 수 있게도 한다.)
방대한 데이터들을 단지 담아만 두고 조회할 목적 => 배열
방대한 데이터들을 빈번하게 추가 ,삭제 ,수정할 목적 => 컬렉션
■ 컬렉션의 3가지 분류
1) List 계열 : 담고자 하는 값(value)만 저장 / 값 저장시 순서 유지가됨(index 개념이 있음) / 중복값 허용
ex) ArrayList, Vector, LinkedList => ArrayList가 제일많이쓰임
2) Set 계열 : 담고자 하는 값(value)만 저장 / 값 저장할때 순서 유지가 안됨(index가 없음) / 중복값 허용x
ex) HashSet, TreeSet
3) Map 계열 : 키(Key) + 담고자 하는 값(value) 세트로 저장/ 값 저장시 순서유지 x / key값은 중복 허용x
ex) HashMap , Properties
■ 제네릭 설정하는 이유
1. 명시한 타입의 객체만 저장가능하도록 타입을 제한하기 위해서 ==> 안정성 확보 가능
2. 컬렉션에 저장된 객체를 꺼내서 사용할때 매번 형변환 하는 절차를 없애기 위해서
▶ List계열
■ ArrayList
● Music 클래스 생성
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 other) {
// 현재 객체와 매개변수로 전달받은 객체간의 비교 수행
/*
* 양수 : 자리유지
* 0 : 자리유지
* 음수 : 자리바꿈
*/
// 가수 기준으로 오름차순정렬
return this.artist.compareTo(other.artist);
}
}
● ListRun 클래스 생성 (main 메서드 포함)
public class ListRun {
public void static main(String[] args) {
}
}
■ main 메서드 안에서 Music Element 선언 후 메서드 알아보기
// 일반적인 배열 선언
ArrayList list = new ArrayList();
// 일반적인 ArrayList 선언
ArrayList<E> list = new ArrayList<E>();
// 객체 생성시에는 생략가능(JDK 7버전이상에서만가능)
ArrayList<Music> list = new ArrayList<>(3);
// <E> --> Element
1. add(E e) : 해당 리스트의 끝에 전달된 e를 추가시켜주는 메소드
list.add(new Music("zero","뉴진스"));
list.add(new Music("ditto","유진스"));
list.add(new Music("hypeboy","가진스"));
list.add(new Music("test","뉴생성자"));
<결과>
[Music [title=zero, artist=뉴진스], Music [title=ditto, artist=유진스], Music [title=hypeboy, artist=듀진스], Music [title=test, artist=규진스]]
1-1. list.add("");
- 순서가 유지되면서 값이 추가가 된다.(각 index에 값이 담겨있음)
- 크기에 제약이 없다. 다양한 타입의 값 추가 가능하다.(권장하진 않음)
2. add(int index, E e) : 리스트에 전달되는 index 값 위치에 전달되는 e를 추가시켜주는 메소드
list.add(1 , new Music("바다의 왕자","박명수"));
<결과>
[Music [title=zero, artist=뉴진스], Music [title=바다의 왕자, artist=박명수], Music [title=ditto, artist=유진스], Music [title=hypeboy, artist=듀진스], Music [title=test, artist=규진스]]
3. set(int index, E e) : 리스트에 해당 인덱스 값을 전달되는 e로 변경시켜주는 메서드
list.set(0, new Music("heart", "뉴진스"));
<결과>
[Music [title=heart, artist=뉴진스], Music [title=바다의 왕자, artist=박명수], Music [title=ditto, artist=유진스], Music [title=hypeboy, artist=듀진스], Music [title=test, artist=규진스]]
4. remove(int index) : 리스트에 해당 인덱스 값을 삭제시켜주는 메서드
list.remove(1);
<결과>
[Music [title=heart, artist=뉴진스], Music [title=ditto, artist=유진스], Music [title=hypeboy, artist=듀진스], Music [title=test, artist=규진스]]
5. size() : 리스트에 담겨있는 데이터의 수를 반환해주는 메서드 == 배열의 length
System.out.println("리스트에 담긴 데이터 수 : " + list.size());
System.out.println("리스트의 마지막 인덱스 : " + (list.size()-1));
<결과>
리스트에 담긴 데이터 수 : 4
리스트의 마지막 인덱스 : 3
6. get(int index) : E => 리스트에 해당 index위치의 데이터를 반환해주는 메서드
1) 제네릭 설정 전
Music m = (Music)list.get(0);
2) 제네릭 설정 후
Music m = list.get(0);
System.out.println(m);
System.out.println(m.getTitle());
System.out.println(list.get(1).getTitle());
<결과>
Music [title=heart, artist=뉴진스]
heart
ditto
■ main 메서드 안에서 Integer Element 선언 후 메서드 알아보기
ArrayList<Integer> iList = new ArrayList();
iList.add(1);
iList.add(2);
iList.add(100);
7. contains(E e) : boolean : 컬렉션안에 매개인자요소를 포함하고 있는지 검사
System.out.println(iList.contains(3));
<결과>
false
8. indexOf(E e) : int : 컬렉션안에 매개인자요소가 몇번째 인덱스에 있는가?
System.out.println(iList.indexOf(3));
<결과>
-1
위의 코드는 3 인덱스에 값이 없으므로 -1이 반환된 것이다.
9. subList(int index1, int index2) : 해당 리스트로부터 index1에서부터 index2까지 데이터의 값들을 추출해서 새로운 List로 반환시켜주는 메서드
List<Music> sub = list.subList(0, 2);
System.out.println(sub);
<결과>
[Music [title=heart, artist=뉴진스], Music [title=ditto, artist=유진스]]
10. addAll(Collection c) : 해당 리스트에 다른 컬렉션에 있는 데이터들을 통채로 추가시켜주는 메서드
list.addAll(sub);
System.out.println(list);
<결과>
[Music [title=heart, artist=뉴진스], Music [title=ditto, artist=유진스], Music [title=hypeboy, artist=듀진스], Music [title=test, artist=규진스], Music [title=heart, artist=뉴진스], Music [title=ditto, artist=유진스]]
11. isEmpty() : 해당 리스트가 비어있는지 묻는 메서드(비었다면 true / 아니면 false 반환)
System.out.println("리스트가 비어있습니까? " + list.isEmpty());
<결과>
리스트가 비어있습니까? false
12. clear() : 리스트를 싹 비워주는 메서드
list.clear();
System.out.println("리스트가 비어있습니까? " + list.isEmpty());
<결과>
리스트가 비어있습니까? ture
13. shuffle : 컬렉션의 내부요소를 랜덤하게 섞어준다.
Collections.shuffle(list);
System.out.println(list);
<결과>
[Music [title=ditto, artist=유진스], Music [title=heart, artist=뉴진스], Music [title=test, artist=규진스], Music [title=ditto, artist=유진스], Music [title=heart, artist=뉴진스], Music [title=hypeboy, artist=듀진스]]
■ main 메서드 안에서 String Element 선언 후 메서드 알아보기
ArrayList<String> sList = new ArrayList();
sList.add("가동현");
sList.add("나동현");
sList.add("다동현");
sList.add("라동현");
14. sort(List list) : 컬렉션을 정렬
1) 기본정렬(가나다라, 1234)에 따라 정렬
Collections.sort(sList);
System.out.println(sList);
[가동현, 나동현, 다동현, 라동현]
2) 역순으로 정렬
Comparator<String> comp = Collections.reverseOrder();
Collections.sort(sList, comp);
System.out.println(sList);
<결과>
[라동현, 다동현, 나동현, 가동현]
▶ 객체 정렬하기
내가 직접 정의한 객체들을 정렬하기 위해서는 정렬기준을 직접 만들어줘야한다.
객체정렬방법은 크게 2종류가 있다.
1. Comparable 인터페이스 구현
- 기본정렬(한가지) 클래스 내부에 직접 구현
- compareTo메서드 오버라이딩함 => 정렬기준은 딱 하나만 세울 수 있다.
ex) 가수이름 오름차순, 가수이름 내림차순, 노래제목 오름차순, 노래제목 내림차순
2. Comparator 인터페이스 구현
- 기본정렬 외에 추가적으로 정렬기준을 제시해야 할 때 별도의 Comparator구현 클래스를 작성하면 된다. (정렬기준에 대한 개수 제한이 없다.)
- compare메서드를 오버라이딩해야한다.
■ MusicTitleAscending 클래스 생성 (Comparator 인터페이스 구현)
public class MusicTitleAscending implements Comparator<Music> {
// 제목 기준 오름차순
@Override
public int compare(Music s1, Music s2) { //
return s1.getTitle().compareTo(s2.getTitle());
}
}
기본정렬 : 가수이름 오름차순
Collections.sort(list);
System.out.println(list);
<결과>
[Music [title=test, artist=규진스], Music [title=heart, artist=뉴진스], Music [title=heart, artist=뉴진스], Music [title=hypeboy, artist=듀진스], Music [title=ditto, artist=유진스], Music [title=ditto, artist=유진스]]
● 추가적인 정렬기준 생성
1. 제목기준 오름차순
Collections.sort(list, new MusicTitleAscending());
System.out.println(list);
<결과>
[Music [title=ditto, artist=유진스], Music [title=ditto, artist=유진스], Music [title=heart, artist=뉴진스], Music [title=heart, artist=뉴진스], Music [title=hypeboy, artist=듀진스], Music [title=test, artist=규진스]]
2. 제목기준 내림차순
Collections.sort(list, new MusicTitleAscending().reversed());
System.out.println(list);
<결과>
[Music [title=test, artist=규진스], Music [title=hypeboy, artist=듀진스], Music [title=heart, artist=뉴진스], Music [title=heart, artist=뉴진스], Music [title=ditto, artist=유진스], Music [title=ditto, artist=유진스]]
■ 컬렉션을 반복시키는 방법
1. 기본 for 문
2. for Each문 : 향상된 반복문
for (Music mu : list) {
System.out.println(mu);
}
<결과>
Music [title=heart, artist=뉴진스]
Music [title=ditto, artist=유진스]
Music [title=hypeboy, artist=듀진스]
Music [title=test, artist=규진스]
3. Iterator 반복자 : 컬렉션의 내부 인자들을 Iterator안에 담아서 관리(String의 StringTokenizer와 비슷)
Iterator<Music> iter = list.iterator();
while (iter.hasNext()) { // hasMoreTokens
Music m2 = iter.next();
System.out.println(m2);
}
<결과>
Music [title=heart, artist=뉴진스]
Music [title=ditto, artist=유진스]
Music [title=hypeboy, artist=듀진스]
Music [title=test, artist=규진스]
■ 반복문을 통해 컬렉션에 담긴 요소가 1이라면 삭제하기
ArrayList<Integer> list2 = new ArrayList();
list2.add(1);
list2.add(1);
list2.add(3);
list2.add(3);
list2.add(5);
1. 향상된 반복문 활용하여 삭제해보기
for (Integer i : list2) {
if (i == 1) {
list2.remove(i);
}
}
- ConcurrentModificationException => 향상된 반복문에서 중간에 요소를 삭제하고자한다면 발생한다.
- 삭제시 index가 변경되면서 반복이 제대로 진행되지 않기 때문에 발생하는 에러
2. 기본 loop문
for (int i = 0; i < list2.size(); i++) {
if (list2.get(i) == 1) {
list2.remove(i);
i--;
}
}
- 삭제가 되는 순간 size의 사이즈가 1 작아진다. 따라서 i-- 해결이 가능하지만 생각하기 어렵고 경우에 따라 놓치는 경우가 있다.
3. Iterator 사용하기(가장 좋은 방법)
Iterator<Integer> iter2 = list2.iterator();
while (iter2.hasNext()) {
int s = iter2.next();
if (s == 1) {
iter2.remove(); // 현재 가리키고 있는 요소를 제거해주는 함수
}
}
System.out.println(list2);
<결과>
[3, 3, 5]
▶ Set계열
■ Set의 특징
- 중복을 허용하지 않는다.
- 지정된 순서를 보장하지 않는다.
LinkedHashSet : 중복을 허용하지 않는다. 저장된 순서를 유지해준다.
TreeSet : 중복을 허용하지 않는다. 오름차순을 자동으로 지원
■ HashSet
● SetRun 클래스 생성 (main 메서드 포함) 후 String Element를 포함한 HashSet 생성
public class SetRun {
public static void main(String[] args) {
HashSet<String> hs1 = new HashSet();
}
}
1. 값추가 : add(추가할 값)
hs1.add(new String("안녕하세요"));
hs1.add(new String("반갑습니다"));
hs1.add(new String("여러분"));
hs1.add("안녕하세요");
hs1.add("반갑습니다");
System.out.println(hs1);
<결과>
[안녕하세요, 반갑습니다, 여러분]
중복값이 들어가지 않고 순서 유지가 되지 않는다.
2. 크기 구하기 : size()
System.out.println(hs1.size());
<결과>
3
3. 값 삭제 : remove(삭제할 값)
hs1.remove("여러분");
System.out.println(hs1);
<결과>
[안녕하세요, 반갑습니다]
4. 모든 값 삭제 : clear()
hs1.clear();
System.out.println(hs1);
<결과>
[]
● Student 클래스 생성
public class Student {
private String name;
private int age;
private int score;
public Student() {
}
public Student(String name, int age, int score) {
super();
this.name = name;
this.age = age;
this.score = score;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", score=" + score + "]";
}
/*
* equals()
*
* 필드값이 모두 동일하면 true가 나올 수 있도록 재작성하기.
* name, age, score
*
* 문자열.equals(문자열)
*
* equals() 와 hashCode()는 동시에 오버라이딩한다.
* equals 결과가 true면 hashCode값도 동일해야 한다. (동일한 객체로 취급)
*/
@Override
public boolean equals(Object o) {
// Student other = (Student) o; 만약 매개변수로 넘어온 객체가 Student가 아니라면 형변환 에러가 발생할 수 있다.
// 형변환 전에 타입검사해주기
if (!(o instanceof Student)) {
return false;
}
Student other = (Student) o;
if (!this.name.equals(other.name)) {
return false;
}
if (this.age != other.age) {
return false;
}
if (this.score != other.score) {
return false;
}
return true;
}
/*
* equals에 사용한 필드를 똑같이 이용해서 hashCode생성하기
*/
@Override
public int hashCode() {
// hashCode생성 메서드 => java 7버전 이상부터 사용 가능
return Objects.hash(name, age, score);
}
}
■ Student Element를 포함한 HashSet 객체 생성 및 초기화
HashSet<Student> hs2 = new HashSet();
hs2.add(new Student("공유", 40, 100));
hs2.add(new Student("홍길동", 30, 90));
hs2.add(new Student("김갑생", 20, 80));
hs2.add(new Student("공유", 40, 100));
System.out.println(hs2);
<결과>
[Student [name=홍길동, age=30, score=90], Student [name=김갑생, age=20, score=80], Student [name=공유, age=40, score=100], Student [name=공유, age=40, score=100]]
Set의 특징으로 중복이 허용되지 안되는데 어째서 똑같은 객체(공유)가 두번 출력되는 것일까?
동일 객체로 판단되지 않았기 때문에 그렇다.
값이 추가가 될 때 내부적으로 equals(), hashCode()로 비교 후 둘다 결과가 true면 동일 객체로 판단한다.
HashSet클래스 안에 객체를 담을 때는 내부적으로 equals()와 hashCode()값이 일치하는 지도 비교하기 때문에 둘 다 오버라이딩 해줘야한다.
equals() 함수를 실행했을 때 결과값 true가 나오면서 hashCode() 결과값도 일치하면 동일객체로 판단할 수 있게끔 재정의하면 된다.
Object클래스에 있는 equals() : 객체간의 주소값을 가지고 비교
Object클래스에 있는 hashCode() : 두 객체의 주소값을 기반으로 해서 해시코드값을 만들어서 비교
Student클래스에 equals() 오버라이딩 : 세 필드값이 동일하면 true / 하나라도 다르면 false
Student클래스에 hashCode() 오버라이딩 : 세 필드값을 기반으로 해시코드값을 생성
Integer => hashCode() : 정수값 그대로 반환
String => hashCode() : 문자열기반 해시코드값을 생성해서 반환 (동일한 문자열 == 동일한 hashCode)
■ 담겨있는 객체에 순차적으로 접근하는 법
1. for문 사용(단, 향상된 for문만 사용 가능하다. => index로는 접근이 불가하기 때문이다.)
for (Student s : hs2) {
System.out.println(s);
}
<결과>
Student [name=홍길동, age=30, score=90]
Student [name=김갑생, age=20, score=80]
Student [name=공유, age=40, score=100]
※ Student 클래스에 equals()와 hashCode()를 오버라이딩 한 다음이기 때문에 공유라는 객체가 하나만 나온다.
2. ArrayList 활용하는 방법
2-1. 매개변수가 있는 생성자 활용
ArrayList<Student> list = new ArrayList(hs2);
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
<결과>
Student [name=홍길동, age=30, score=90]
Student [name=김갑생, age=20, score=80]
Student [name=공유, age=40, score=100]
2-2. addAll(Collection c)함수 활용
ArrayList<Student> list = new ArrayList();
list.addAll(hs2);
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
<결과>
Student [name=홍길동, age=30, score=90]
Student [name=김갑생, age=20, score=80]
Student [name=공유, age=40, score=100]
3. HashSet클래스에서 제공하는 Iterator반복자를 이용하는 방법. (hs2에 담겨있는 객체들을 Iterator(반복자)에 담는 과정)
Iterator<Student> it = hs2.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
<결과>
Student [name=홍길동, age=30, score=90]
Student [name=김갑생, age=20, score=80]
Student [name=공유, age=40, score=100]
※ .iterator() : List계열와 Set계열에서만 사용 가능한 메서드(Map 계열에서는 호출 불가)
■ Integer Elemnnet를 포함한 TreeSet 선언 및 초기화
TreeSet<Integer> set = new TreeSet();
set.add(500);
set.add(7);
set.add(0);
set.add(100);
System.out.println(set);
<결과>
[0, 7, 100, 500]
※ TreeSet은 오름차순 정렬이 알아서 되는 Set이다.
■ Integer Elemnnet를 포함한 LinkedHashSet 선언 및 초기화
LinkedHashSet<Integer> set2 = new LinkedHashSet();
set2.add(500);
set2.add(400);
set2.add(300);
set2.add(200);
set2.add(100);
System.out.println(set2);
<결과>
[500, 400, 300, 200, 100]
※ LinkedHashSet은 순서유지가 되는 Set이다.
▶ Map계열
■ Map의 특징
- key, value 한쌍으로 요소를 구성한다.
- key를 통해서 value를 얻어온다.
- key는 중복을 허용하지 않는다. value는 중복되어도 좋다.
- 동일한 key값으로 추가 저장하면, 마지막에 추가한 value값으로 치환된다.(덮어씌우기)
● Student 클래스 생성
public class Snack {
private String flavor;
private int calory;
public Snack() {
}
public Snack(String flavor, int calory) {
super();
this.flavor = flavor;
this.calory = calory;
}
public String getFlavor() {
return flavor;
}
public void setFlavor(String flavor) {
this.flavor = flavor;
}
public int getCalory() {
return calory;
}
public void setCalory(int calory) {
this.calory = calory;
}
@Override
public String toString() {
return "Snack [flavor=" + flavor + ", calory=" + calory + "]";
}
}
● MapRun 클래스 생성 (main 메서드 포함) 후 String key값과 Snack value값을 가진 HashMap 생성
public class MapRun {
public static void main(String[] args) {
HashMap<String, Snack> hm = new HashMap();
}
}
1. put(K key, V value) => map공간에 key + value 세트로 추가해주는 메서드
hm.put("다이제", new Snack("초코맛", 500));
hm.put("칸초", new Snack("단맛", 300));
hm.put("바나나깡", new Snack("바나나맛", 400));
hm.put("씬다이제", new Snack("초코맛", 500));
System.out.println(hm);
hm.put("씬다이제", new Snack("초코맛", 300));
System.out.println(hm);
<결과>
{다이제=Snack [flavor=초코맛, calory=500], 바나나깡=Snack [flavor=바나나맛, calory=400], 칸초=Snack [flavor=단맛, calory=300], 씬다이제=Snack [flavor=초코맛, calory=500]}
{다이제=Snack [flavor=초코맛, calory=500], 바나나깡=Snack [flavor=바나나맛, calory=400], 칸초=Snack [flavor=단맛, calory=300], 씬다이제=Snack [flavor=초코맛, calory=300]}
- 저장순서를 유지해주지 않는다.
- value값이 동일해도 key값만 중복되지 않는다면 데이터 추가에 문제가 없다.
2. get(Object key) : V => 컬렉션에 해당 키값의 value값을 돌려주는 메서드
System.out.println(hm.get("다이제"));
<결과>
Snack [flavor=초코맛, calory=500]
3. size() => 맵에 담겨있는 객체의 개수
System.out.println(hm.size());
<결과>
4
4. replace(K key, V value) => 맵에 해당 key값을 찾아서 전달받은 value값으로 변경해준다.
Snack s2 = hm.replace("바나나깡", new Snack("초코바나나맛", 500));
System.out.println(s2);
System.out.println(hm);
<결과>
Snack [flavor=바나나맛, calory=400]
{다이제=Snack [flavor=초코맛, calory=500], 바나나깡=Snack [flavor=초코바나나맛, calory=500], 칸초=Snack [flavor=단맛, calory=300], 씬다이제=Snack [flavor=초코맛, calory=300]}
5. remove(Object key) => 컬렉션에 해당 key값을 찾아서 key + value 둘다 지워준다.
hm.remove("칸초");
System.out.println(hm);
<결과>
{다이제=Snack [flavor=초코맛, calory=500], 바나나깡=Snack [flavor=초코바나나맛, calory=500], 씬다이제=Snack [flavor=초코맛, calory=300]}
remove() 의 반환값은 삭제된 value값이 반환된다.
■ 순차적으로 HashMap에 담겨있는 값에 접근하고자 할 때
1. keySet : hashMap에 key값들만 따로 Set에 저장시켜주는 함수
2. entrySet : key값과 value값을 하나로 묶어서 Set에 담아주는 함수
앞에 Set에서 했던 향상된 for문 방법은 불가능하다.
iterator()는 List나 Set계열에서만 사용되는 메서드이다. 사용이 불가능하다.
List와 Map은 다른 계열이기 때문에 ArrayList로 담은 후 출력이 불가능하다.
때문에 Map을 Set으로 바꿔주는 메서드를 이용하면 된다.
1. keySet()을 이용하는 방법
1-1. hm에 있는 key값들만 Set에 담기
Set<String> keySet = hm.keySet();
1-2. keySet을 iterator에 담기
Iterator<String> it = keySet.iterator();
1-3. 반복자에 담긴 것들을 순차적으로 뽑기
while (it.hasNext()) {
String key = it.next();
Snack value = hm.get(key);
System.out.println("key : " + key);
System.out.println("value : " + value);
}
<결과>
key : 다이제
value : Snack [flavor=초코맛, calory=500]
key : 바나나깡
value : Snack [flavor=초코바나나맛, calory=500]
key : 씬다이제
value : Snack [flavor=초코맛, calory=300]
2. entrySet() 이용하는 방법
2-1. hm에 있는 key + value 모두 Set에 담아준다.(Entry == 집합형태)
Set<Entry<String, Snack>> entrySet = hm.entrySet();
2-2. entrySet에 있는 것들을 Iterator에 담기
Iterator<Entry<String, Snack>> itEntry = entrySet.iterator();
2-3. 반복자 이용해서 순차적으로 값을 뽑기
while (itEntry.hasNext()) {
Entry<String, Snack> entry = itEntry.next();
System.out.println("key : " + entry.getKey());
System.out.println("value : " + entry.getValue());
}
<결과>
key : 다이제
value : Snack [flavor=초코맛, calory=500]
key : 바나나깡
value : Snack [flavor=초코바나나맛, calory=500]
key : 씬다이제
value : Snack [flavor=초코맛, calory=300]
■ Properties
- Map 계열이며 key, value 세트로 저장된다.
- Properties만의 특징이라고 한다면 key, value 모두 String으로 제한된다.
- 파일 입출력 메서드를 지원하며, 설정정보 표현에 최적의 형태를 가지고 있다.
- Properties를 사용하는 경우에는 Properties에 담겨있는 key + value를 세트로 파일에 기록할 것이다.
- 파일에 기록된 key value를 가지고 올 때도 사용된다.
.properties 사용하는 경우는 해당 프로그램이 기본적으로 가져야 할 정보들을 .properties확장자 문서로 저장해두면 key값, value값이 모두 문자열이기 때문에 개발자가 아닌 일반관리자도 해당문서를 다루기가 쉽다.
.xml 사용하는 경우는 xml확장자 문서자체가 다양한 프로그래밍언어간에 호환이 쉽기 때문에 사용이 된다.
● main 메서드가 포함된 PropertiesTest1 클래스 생성 및 Properties 객체 생성
public class PropertiesTest1 {
public static void main(String[] args) {
Properties prop = new Properties();
}
}
1. setProperty(String key, String value) : 값 담기
prop.setProperty("List", "ArrayList");
prop.setProperty("Set", "HashSet, TreeSet, LinkedHashSet");
prop.setProperty("Map", "HashMap, Properties");
System.out.println(prop);
<결과>
{Set=HashSet, TreeSet, LinkedHashSet, List=ArrayList, Map=HashMap, Properties}
※ 이때 결과 값으로는 저장순서 유지가 안되며 key값 중복도 되지 않는다.
2. getProperty(String key) : String : 값 가져오기
System.out.println(prop.getProperty("Map"));
System.out.println(prop.getProperty("DBID", "HEY")); // 두번째 매개변수는 받고자하는 값이 없을 때 default값을 제시해준다.
<결과>
HashMap, Properties
HEY
3. Store(출력스트림 객체, 코멘트 내용) : Properties안에 담긴 key, value를 파일로 출력
4. storeToXML(출력스트림 객체, 코멘트 내용) : Properties안에 담긴 key, value xml문서에 출력
try {
// 3. Store(출력스트림 객체, 코멘트 내용) : Properties안에 담긴 key, value를 파일로 출력
prop.store(new FileOutputStream("test.properties"), "ABC");
// 4. storeToXML(출력스트림 객체, 코멘트 내용) : Properties안에 담긴 key, value xml문서에 출력
prop.storeToXML(new FileOutputStream("test.xml"), "xml");
} catch (IOException e) {
e.printStackTrace();
}
5. load(입력스트림 객체)
try {
// 5. load(입력스트림 객체)
prop.load(new FileInputStream("test.properties"));
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(prop);
<결과>
{Set=HashSet, TreeSet, LinkedHashSet, List=ArrayList, Map=HashMap, Properties}
6. 요소가져오기
String list = prop.getProperty("List");
System.out.println(list);
<결과>
ArrayList
7. 전체열람
Enumeration<?> en = prop.propertyNames(); // names == key == 키값의 모음
while(en.hasMoreElements()) {
String name = (String)en.nextElement();
String value = prop.getProperty(name);
System.out.println(name + " - " + value);
}
<결과>
Map - HashMap, Properties
List - ArrayList
Set - HashSet, TreeSet, LinkedHashSet
'JAVA' 카테고리의 다른 글
JAVA (30) Thread (0) | 2023.04.19 |
---|---|
JAVA (29) 제네릭(Generic) (0) | 2023.04.19 |
JAVA (27) 보조 스트림 (0) | 2023.04.15 |
JAVA (26) FileCharDao (0) | 2023.04.15 |
JAVA (25) FileByteDao (0) | 2023.04.13 |