2. 콜렉션
2-2. Collection의 주요 하위 인터페이스
2) List<E> 인터페이스의 구현클래스
- ArrayList<E>
- 가장 많이 사용되는 List<E> 인터페이스의 구현 클래스
- 0번째부터 차례대로 저장하기, 0번째부터 차례대로 꺼내기 작업에 가장 적합
- 내부적으로 가변길이 배열을 활용해서 객체에 자동으로 저장
- * ArrayList<E>의 주요 메소드 (=Vector<E>)
- boolean add(E e)
: 리스트의 맨 마지막에 새로운 객체 저장
- void add(int index, E e)
: 리스트의 저장된 위치에 새로운 객체 추가
: 해당 위치부터 맨 마지막 객체들이 전부 한칸씩 뒤로 이동
- boolean addAll(Collenction<? extends E> c)
: 리스트에 다른 콜렉션객체에 저장된 모든 객체가 저장
- boolean addAll(int index, Collection<? extends E> c)
: 리스트의 지정된 위치에 다른 콜렉션객체에 저장된 모든 객체 추가
- void clear()
: 리스트에 저장된 모든 객체 삭제
- boolean contains(Object o)
: 리스트에 저장된 객체가 존재하면 true 반환
- E get(int index)
: 리스트에서 지정된 위치에 저장된 객체 반환
- boolean isEmpty()
: 리스트가 비어있으면 true 반환
- Iterator<E> iterator()
: 리스트에 저장된 객체를 반복처리하는 Iterator객체 반환
- boolean remove(Object o)
: 리스트에서 지정된 객체 삭제
- E remove(int index)
: 리스트에서 지정된 위치에 저장된 객체 삭제
- E set(int index, E e)
: 리스트에서 지정된 위치의 객체를 새 객체로 교체
- int size()
: 리스트에 저장된 객체의 개수를 반환
- * ArrayList<E>의 주요 메소드 (=Vector<E>)
- LinkedList<E>
- 중간에 객체를 삽입하거나, 중간에 저장된 객체를 삭제하는 일이 빈번한 경우에 사용하는 구현 클래스
(속도가 빠름) - 앞뒤 객체와 열차처럼 쌍방 연결 (한 객체에서 previous, next 연결)
- List<E> 인터페이스의 구현 클래스이면서, Queue<E> 인터페이스의 구현 클래스
* Queue<E>는 FIFO(First-In First-Out) 자료구조를 표현하는 인터페이스 - LinkedList<E>의 FIFO 기능을 지원하는 메소드
boolean offer(E item) : 리스트의 last element로 새로운 객체를 추가
E peek() : 리스트의 first element 반환
E poll() : 리스트의 first element를 삭제하고, 그 엘리먼트 반환 - * -------------- ---------------- -------------
* | | | |<----|- | | | <----|- | | |
* E poll() <--- | | 객체 | | | | 객체 | | | | 객체 | | <--- offer(E e)
* | | | -|---->| | | -|----> | | | |
* -------------- ---------------- -------------
- 중간에 객체를 삽입하거나, 중간에 저장된 객체를 삭제하는 일이 빈번한 경우에 사용하는 구현 클래스
- Vector<E>
- ArrayList<E>와 구현이 완전히 동일
- ArrayList<E>는 Thread-unsafe하고, Vector<E>는 Thread-safe
- Stack<E>
- FILO(First-In Last-Out) 자료구조를 구현한 객체
- Stack<E>의 고유 기능을 지원하는 메소드
E push(E item) : Stack에 새로운 객체를 저장
E peek() : Stack의 맨 꼭대기에 위치한 객체를 반환
E pop() : Stack의 맨 꼭대기에 위치한 객체를 삭제하고, 그 객체를 반환
* E push(E item) E pop()
* | ∧
* | |
* ∨ |
* ----------------------------
* | |
* ----------------------------
* | |
* ----------------------------
* | |
* ----------------------------
* | |
* ----------------------------
-ArrayList에 값 추가하고 출력하기
import java.util.ArrayList;
public class ListApp1 {
public static void main(String[] args) {
ArrayList<String> names = new ArrayList<>();
names.add("홍길동");
names.add("김유신");
names.add("홍길동");
names.add("강감찬");
names.add("홍길동");
names.add("이순신");
names.add("홍길동");
names.add("류관순");
for(String name : names) {
System.out.println("이름: "+name);
}
}
}
이름: 홍길동
이름: 김유신
이름: 홍길동
이름: 강감찬
이름: 홍길동
이름: 이순신
이름: 홍길동
이름: 류관순
-ArrayList 메소드 이용해보기
import java.util.ArrayList;
public class ListApp2 {
public static void main(String[] args) {
ArrayList<String> names = new ArrayList<>(); // ArrayList를 Vector로 바꿔도 똑같음
// boolean add(E e)를 사용해서 리스트에 객체 추가하기
names.add("홍길동");
names.add("김유신");
names.add("강감찬"); // String객체만의 특징(toString안써도 됨)
System.out.println(names); // 향상된for문으로도 출력가능
// void add(int index, E e)를 사용해서 리스트에 객체 추가하기
names.add(1,"류관순");
System.out.println(names);
// E get(int index)를 사용해서 리스트에 저장된 객체 조회하기
System.out.println(names.get(0));
System.out.println(names.get(1));
System.out.println(names.get(2));
System.out.println(names.get(3));
// E set(int index, E e)를 사용해서 리스트에 저장된 객체 교체하기
names.set(2, "윤봉길");
System.out.println(names);
// void clear()를 사용해서 리스트에 저장된 객체 삭제하기
names.clear();
System.out.println(names);
}
}
[홍길동, 김유신, 강감찬]
[홍길동, 류관순, 김유신, 강감찬]
홍길동
류관순
김유신
강감찬
[홍길동, 류관순, 윤봉길, 강감찬]
[]
-stack 메소드 이용해보기
import java.util.Stack;
public class ListApp3 {
public static void main(String[] args) {
Stack<String> stack = new Stack<>();
stack.push("홍길동1");
stack.push("홍길동2");
stack.push("홍길동3");
stack.push("홍길동4");
stack.push("홍길동5");
System.out.println(stack);
String name1 = stack.pop(); // pop메소드의 반환값 = String
System.out.println(name1);
System.out.println(stack);
String name2 = stack.pop(); // pop메소드의 반환값 = String
System.out.println(name2);
System.out.println(stack);
String name3 = stack.pop(); // pop메소드의 반환값 = String
System.out.println(name3);
System.out.println(stack);
String name4 = stack.pop(); // pop메소드의 반환값 = String
System.out.println(name4);
System.out.println(stack);
String name5 = stack.pop(); // pop메소드의 반환값 = String
System.out.println(name5);
System.out.println(stack);
}
}
[홍길동1, 홍길동2, 홍길동3, 홍길동4, 홍길동5]
홍길동5
[홍길동1, 홍길동2, 홍길동3, 홍길동4]
홍길동4
[홍길동1, 홍길동2, 홍길동3]
홍길동3
[홍길동1, 홍길동2]
홍길동2
[홍길동1]
홍길동1
[]
3) Iterator<E>
- 인터페이스이다.
- 콜렉션에 대한 반복작업을 수행하는 객체들이 구현할 기능이 정의되어 있다.
- 향상된 for문이 제공되기 전까지 콜렉션에 저장된 객체들을 반복처리할 때 Iterator<E> 구현객체를 사용했다.
- 주요 메소드
- boolean hasNext() : 반복처리할 객체가 남아 있으면 true 반환, false가 나올 때까지 반복
E next() : 객체를 꺼낸다
void remove() : 이번 반복작업에서 다루고 객체를 삭제
- boolean hasNext() : 반복처리할 객체가 남아 있으면 true 반환, false가 나올 때까지 반복
- Iterator<E> 인터페이스의 구현객체를 획득하는 방법
- Collection<E> 인터페이스를 구현한 모든 자료구조 구현 객체는
Iterator<E> 구현 객체를 제공하는 iterator() 메소드가 있다.
- Collection<E> 인터페이스를 구현한 모든 자료구조 구현 객체는
-
import java.util.ArrayList;
import java.util.Iterator;
public class ListApp1 {
public static void main(String[] args) {
ArrayList<String> names = new ArrayList<>();
names.add("홍길동");
names.add("김유신");
names.add("홍길동");
names.add("강감찬");
names.add("홍길동");
names.add("이순신");
names.add("홍길동");
names.add("류관순");
Iterator<String> itr = names.iterator();
while(itr.hasNext()) {
String name = itr.next();
System.out.println(name);
}
}
}
홍길동
김유신
홍길동
강감찬
홍길동
이순신
홍길동
류관순
import java.util.Iterator;
import java.util.Set;
public class SetApp1 {
public static void main(String[] args) {
Set<String> names = Set.of("이순신", "김유신", "강감찬", "류관순", "윤봉길"); //간단하게 Set을 만들 떄
Iterator<String> itr = names.iterator(); // iterator의 반환값이 Iterator인데, 우리가 String을 다루고 있으니까 <String>
System.out.println(itr.hasNext());
System.out.println(itr.next()); // set이니까 순서는 없음(다음 객체 아무거나 반환)
System.out.println(itr.hasNext());
System.out.println(itr.next());
System.out.println(itr.hasNext());
System.out.println(itr.next());
System.out.println(itr.hasNext());
System.out.println(itr.next());
System.out.println(itr.hasNext());
System.out.println(itr.next());
System.out.println(itr.hasNext());
System.out.println(itr.next());
}
}
true
강감찬
true
류관순
true
윤봉길
true
김유신
true
이순신
false
Exception in thread "main" java.util.NoSuchElementException
at java.base/java.util.ImmutableCollections$SetN$SetNIterator.next(ImmutableCollections.java:981)
at day23.collection.iterator.SetApp1.main(SetApp1.java:24)
===> hasNext() : 반복할 객체가 남아 있으면 true, 반복할 객체가 없으면 false
===> true인 동안만 반복
===> while문 필요
4) while문
반복문
for문
for ( 초기식; 조건식; 증감식 ) {
수행문;
}
for ( 타입 변수명 : 배열혹은콜렉션 ) {
수행문;
}
- while ( 조건식 ) {
수행문;
} - 조건식이 true로 판정되면 수행문을 실행
- 조건식이 반복작업을 지속할지 여부를 결정
- while문은 반복작업을 지속할지 여부를 알려주는 기능이 제공되는 객체에 대해서만 사용
- 대표적인 객체
- Iterator<E> : boolean hasNext() 반복처리할 객체가 남아있으면 true
E next() 객체를 꺼낸다 - Enumeration<E> : boolean hasMoreElements() 반복처리할 요소(객체)가 남아있으면 true
E nextElement() 요소를 꺼낸다 - StringTokenizer : boolean hasMoreTokens() 반복처리할 토큰(문자열)이 남아있으면 true
String nextToken() 토큰을 꺼낸다 - ResultSet : boolean next() 반복처리할 행이 존재하면 true
int getInt(String columnName) 행에서 지정된 컬럼의 값을 꺼낸다
long getLong(String columnName)
double getDouble(String columnName)
String getString(String columnName)
Date getDate(String columnName) - 사용예)
List<Set> nameSet = new HashSet<>();
// ~~ 객체를 추가하는 작업(nameSet.add)은 생략
Iterator<String> itr = nameSet.iterator();
while(itr.hasNext()) {
String name = itr.next();
}
- Iterator<E> : boolean hasNext() 반복처리할 객체가 남아있으면 true
- 반복작업 처리
1) 향상된 for문 (거의 얘를 사용해)
2) Iterator<E>
근데, 반복문 수행 중에 내가 원하는 객체를 삭제하고 싶다? -> 향상된 for문 불가 -> Iterator<E> 사용
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class SetApp1 {
public static void main(String[] args) {
Set<String> names = new HashSet<>();
names.add("김유신");
names.add("강감찬");
names.add("이순신");
names.add("류관순");
names.add("윤봉길");
// 반복문 처리 1) 향상된 for문을 사용해서 반복작업 수행하기
System.out.println("### 향상된 for문을 사용해서 콜렉션 객체에 저장된 객체들을 반복처리하기");
for(String name : names) {
System.out.println(name);
// 향상된 for문 내부에서는 콜렉션에 저장된 객체를 절대로 삭제할 수 없다.
// if(name.equals("김유신")) {
// names.remove("김유신");
// }
}
// 반복문 처리 2) Iterator<E> 객체를 획득해서 반복작업 수행하기 (훨씬 복잡함)
System.out.println("### Iterator를 사용해서 콜렉션 객체에 저장된 객체들을 반복처리하기");
Iterator<String> itr = names.iterator();
while(itr.hasNext()) {
String name = itr.next();
System.out.println(name);
// 콜렉션의 객체들을 반복처리하면서 특정 객체를 삭제할 수 있다.
if(name.equals("김유신")) {
itr.remove();
}
}
System.out.println(names);
}
}
### 향상된 for문을 사용해서 콜렉션 객체에 저장된 객체들을 반복처리하기
윤봉길
김유신
류관순
강감찬
이순신
### Iterator를 사용해서 콜렉션 객체에 저장된 객체들을 반복처리하기
윤봉길
김유신
류관순
강감찬
이순신
[윤봉길, 류관순, 강감찬, 이순신]
- iterator()를 실행한 결과로 반환된 객체는 Iterator 인터페이스를 구현함
HashSet<String> 객체가 만들어지고 그 안에 "string"들이 있음
이 Set객체 안에서 Iterator()를 실행하면, Iterator<String> 인터페이스를 구현한 객체가 반환됨
이 Iterator<String> 구현객체는 Iterator<String> 인터페이스를 가지고 있고, 그 안의 메소드들을 재정의 함
그리고 구현객체에서는 반복작업을 하니까, Set객체의 string 객체들의 주소값을 가지고 있을거야
그러면 hasNext()를 실행했을 때, 내부적으로 return position < limit; 일때 true값 반환 이런식으로 실행
next()를 실행했을 때도 { String value = values[position]; position++; return value; } 이런식으로
값을 증가시켜가면서 반환하는 기능이 구현되어 있을거야
그래서 알아서 position을 증가시켜가면서 반복작업을 수행
그리고,
iterator()를 실행하면 인터페이스를 구현한 객체가 나와야되는데, 반환타입이 Iterator 이니까,
실제로는 참조변수 iter가 Iterator 인터페이스를 바라보고 있음 ( 클래스 형변환 )
이때 iterator의 메소드를 실행하면, 재정의된 메소드가 실행
따라서, 우리는 구현클래스의 구체적인 이름을 몰라도 됨
( 어차피 인터페이스로 클래스 형변환 될거고, 메소드 재정의가 자동으로 실행되니까 )
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ListApp1 {
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("홍길동");
names.add("김유신");
names.add("홍길동");
names.add("강감찬");
names.add("홍길동");
names.add("이순신");
names.add("홍길동");
names.add("류관순");
names.add("김유신");
Iterator<String> itr = names.iterator();
while(itr.hasNext()) {
String name = itr.next();
System.out.println(name);
}
}
}
홍길동
김유신
홍길동
강감찬
홍길동
이순신
홍길동
류관순
김유신
* 배열/콜렉션에 대한 반복작업 처리할 때
1순위)
향상된 for문 사용
2순위)
<삭제작업을 할 때>
Iterator 사용
(반복작업을 처리하면서 콜렉션에 저장된 객체를 삭제해야 되는 경우에만! - for문에서는 삭제가 안됨)
<index를 사용해야 할 때> (Set<E> 구현객체는 사용불가 - index가 없어서 몇번째인지 알 수 없어)
for문
List는 향상for문, iterator, index 모두 쓸 수 있음 (순서도 있음)
Set은 향상for문, iterator만 사용 가능
2-3. Null 체크
* 콜렉션
- 인덱스, 배열크기 신경 안써도 됨 (자동으로 설정)
- n개의 배열크기가 있을 때, 배열은 값이 없는 것(null값)까지 꺼내오는데,
얘는 실제 값이 들어있는 값까지만 꺼냄 -> null값 검사 필요 x
* null 체크를 이렇게 해도 됨!
if(customer != null) {
수행문 실행 ~~
} else if {
"[오류] 존재하지 않습니다."
}
* null 체크
1) 반환타입이 기본자료형
public int method() { ... }
int value = x.method();
System.out.println(value);
* null이 반환되지 않음
2) 반환타입이 참조자료형이고 객체 하나가 반환된다.
public Book method() { ... }
Book obj = x.method();
* obj는 null을 가질 수 있다. ( 객체 하나가 반환되거나, null이 반환되거나 이니까 )
* obj는 Book객체의 참조값을 가질 수 있다.
if( obj != null ) {
System.out.println(obj.getTitle());
} else {
System.out.println("책정보가 존재하지 않습니다.");
}
3) 반환타입이 참조자료형이고, 콜렉션(List, Set, Map)이 반환된다. (객체가 여러개)
public List<Book> method() { ... }
List<Book> book = x.method();
* book은 절대로 null이 반환되게 하지 않는다. (null 값을 가지지 않는다.)
( 배열은 값이 들어있지 않은 객체(null)까지 반환하지만, 콜렉션은 값이 들어있는 객체만 반환하기 때문 )
* 따라서 null값이 아닌, 콜렉션이 비어있는지를 확인
if( !books.isEmpty ) { ---> 비어있지 않으면
for (Book book : books) {
System.out.println(book.getTitle());
}
} else {
System.out.println("책정보가 존재하지 않습니다.");
}
'수업내용 > Java' 카테고리의 다른 글
[2022.10.07.금] 예외처리 (0) | 2022.10.07 |
---|---|
[2022.10.06.목] List 실습, Map<K, V> 인터페이스 (0) | 2022.10.06 |
[2022.10.04.화] 제네릭, 콜렉션(set<E>) (0) | 2022.10.05 |
[2022.09.30.금] Date, Format, Math 클래스 (0) | 2022.10.01 |
[2022.09.29.목] 학생, 성적 처리 실습 (0) | 2022.09.30 |