Java에서 제공해주는 ‘자료구조’
요소를 수집해서 저장하는 것, 다수개의 객체를 저장해 두고 필요할 때 마다 꺼내서 사용하는 경우를 위해 컬렉션을 사용한다. 데이터를 추가, 검색, 삭제하는데 가장 간단한 방법은 배열이 있는데, 배열의 단점은 초기에 선언을 해줄 때 배열의 전체 크기가 고정이 된다. 처음에 선언한 개수 만큼만 사용이 가능하고, 그것을 초과하면 문제가 생긴다. 이 부분은 불특정 다수의 객체를 저장하기에는 문제가 있고, 또 다른 문제점으로는 객체를 삭제했을 때 해당 인덱스가 비게 되어 낱알이 듬성듬성 빠진 옥수수가 될 수 있다. 이 때문에 새로운 객체를 저장하려면 어디가 비어있는지 확인하는 코드가 필요하다. 이를 보완하기 위해 사용하는 것이 ArrayList이다. 값을 유연하게 저장할 수 있다.
ArrayList list = new ArrayList();
list.add();
list.add();
list.add();
자바는 배열의 이런 문제점을 해결하고, 널리 알려져 있는 자료구조를 바탕으로 객체들을 효율적으로 추가,삭제,검색할 수 있도록 java.util 패키지에 컬렉션과 관련된 인터페이스와 클래스들을 포함시켜 놓았는데, 이들을 총칭해서 컬렉션이라고 한다.


List와 Set은 객체를 추가, 삭제, 검색하는 방법에 많은 공통점이 있는데 이 인터페이스들의 공통된 메소드만 모아 Collection 인터페이스로 정의해 두고 있다.
List는 중복 저장이 가능하고,데이터를 순서대로 유지하고 저장함으로 index로 탐색이 가능하다.(중복 상관없이 데이터 순서대로 사용하고 싶을 때)
Set은 중복 저장이 불가한 특징이 있는데, 같은 데이터로 인식이 되면 중복을 걸러주며, index로 탐색이 불가하다. 데이터의 저장 순서를 보장할 수 없다는 특징이 있다. (중복 제거할 때 사용)
Map은 키(Key)와 값(Value)을 하나의 쌍으로 묶어서 관리하는 구조로 되어있는데, 같은 키 값이면 중복 저장이 불가하고 마지막 키 값으로 덮어쓰는 특징이 있다. List나 Set과는 자료구조의 사용 방법이 전혀 다르다. (키와 값을 한쌍으로 사용하고 싶을 때 사용)
List<> List = new
List컬렉션을 객체를 일렬로 늘어놓은 구조를 가지고 있다. 각각의 인덱스마다 객체를 바라보고 있기 때문에 자료형의 개수가 계속 변하는 상황에서 유리한 자료구조 형태이다. List 컬렉션은 객체 자체를 저장하는게 아니라 객체의 번지를 참조하고, null도 저장이 가능한데, null의 경우 해당 인덱스는 객체를 참조하지 않는다.

// List 컬렉션에 저장되는 구체적인 타입을 String으로 정해놓고 추가, 찾기, 그리고 삭제하는 것을 코드
List<String> list = ...;
list.add("홍길동");
list.add(1, "삼길동");
String str = list.get(1);
list.remove(0);
list.remove("삼길동");
// 전체 객체를 대상으로 하나씩 반복해서 저장된 객체를 얻고싶을 때
List<String> list = ...;
for (int i = 0; i < list.size; i++) {
String str = list.get(i); // i 인덱스에 저장된 String 객체를 가져옴
}
// 인덱스 번호가 필요 없다면 향상된 for문을 이용하는 것이 편리함
for (String str : list) { // 저장된 list 총 갯수만큼 루핑
}
List 컬렉션에서 공통적으로 사용 가능한 List 인터페이스의 메소드
| 기능 | 메소드 | 설명 |
|---|---|---|
| 객체 추가 | boolean add(E e) | 주어진 객체를 맨 끝에 추가 |
| void add(int index, E element) | 주어진 인덱스에 객체를 추가 | |
| set(int index, E element) | 주어진 인덱스에 저장된 객체를 주어진 객체로 바꿈 | |
| 객체 검색 | boolean contains(Object o) | 주어진 객체가 저장되어있는지 여부 |
| E get(int index) | 주어진 인덱스에 저장된 객체를 리턴 | |
| isEmpty() | 컬렉션이 비어있는지 여부 | |
| int size() | 저장되어 있는 전체 객체 수 리턴 | |
| 객체 삭제 | void clear() | 저장된 모든 객체를 삭제 |
| E remove(int index) | 주어진 인덱스에 저장된 객체를 삭제 | |
| boolean remove(Object o) | 주어진 객체를 삭제 |
List 인터페이스의 구현 클래스, ArrayList에 객체를 추가하게 되면 객체가 인덱스로 관리된다. 일반 배열과 ArrayList는 인덱스로 객체를 관리한다는 점에서는 같지만, 배열은 생성할 때 크기가 고정되고 사용 중에 크기를 변경할 수 없지만, ArrayList는 저장 용량(capacity)를 초과한 객체들이 들어오면 자동적으로 저장 용량이 늘어난다.

기본 생성자로 ArrayList를 생성하면 내부에 10의 객체를 저장할 수 있는 초기 용량을 가지게 된다. 저장되는 객체 수가 늘어나면 용량이 자동으로 증가하지만, 처음부터 용량을 크게 잡고 싶다면 크기를 매개값으로 넣는 생성자를 이용하면 된다.
List<String> list = new ArrayList<String>(30); // String 객체 30개 저장할 수 있는 용량 선언
ArrayList에 객체를 추가하면 인덱스 0부터 차례대로 저장된다. ArrayList에서 특정 인덱스의 객체를 제거하면 바로 뒤 인덱스부터 마지막 인덱스까지 모두 앞으로 1씩 당겨지고, 특정 인덱스에 객체를 삽입하면 해당 인덱스부터 마지막 인덱스까지 모두 1씩 밀려나는 특징을 가지고 있어서 빈번한 객체 삭제와 삽입이 일어나는 곳에서는 ArrayList를 사용하는 것이 바람직하지 않다.
이 경우라면, LinkedList(객체의 삽입과 삭제가 빠름)를 사용하는 것이 좋으나, 인덱스 검색, 맨마지막에 객체를 추가하는 경우라면 ArrayList가 더 좋은 성능을 발휘한다.
arrayList의 최악의 시간 복잡도 O(N)
package chap11.list;
import java.util.*;
public class ArrayListExample {
public static void main(String[] args){
// ArrayList 값 추가
List<String> list = new ArrayList<>(); // 아무런 숫자를 입력 하지 않아도 내부적으로 10개의 사이즈가 할당됨
// String 객체를 저장
list.add("Java");
list.add("Spring");
list.add("Servlet/JSP");
list.add("DBMS");
list.add("JPA");
// 추가된 객체의 총 개수 출력
System.out.println("총 개수 : " + list.size());
// 값 순회 하면서 출력
for(int i = 0; i < list.size(); i++){
System.out.println("\t" + i + " : " + list.get(i));
}
// 값 삭제
list.remove(2);
list.remove(2);
list.remove("JPA");
for(String element : list){
System.out.println("\t" + element);
}
}
}
List 구현 클래스임으로 ArrayList와 사용 방법은 똑같지만 내부 구조는 다르다, ArrayList는 내부 배열에 객체를 저장해서 인덱스로 관리하지만, LinkedList는 인접 참조를 링크해서 체인처럼 관리한다.

LinkedList에서 특정 인덱스의 객체를 제거하면 앞뒤 링크만 변경되고 나머지 링크는 변경되지 않는다. 특정 인덱스에 객체를 삽입할 때도 마찬가지이며, ArrayList는 중간 인덱스의 객체를 제거하면 뒤에 객체는 인덱스가 1씩 앞으로 당겨지기 때문에 빈번한 객체 삭제와 삽입에 불리하다.
LinkedList 의 시간 복잡도 : O(1)
LinkedList를 생성하기 위해서는 저장할 객체 타입을 타입 파라미터(E)에 표기하고 기본 생성자를 호출하면 된다. LinkedList가 처음 생성될 때에는 어떠한 링크도 만들어지지 않았기 때문에 내부는 비어있다.
List<E> list = new LinkedList<E>();
package chap11.list;
import java.util.*;
public class LinkedListExample {
public static void main(String[] args){
// LinkedList 값 추가
List<String> list = new LinkedList<>();
// String 객체를 저장
list.add("Java");
list.add("Spring");
list.add("Servlet/JSP");
list.add("DBMS");
list.add("JPA");
// 추가된 객체의 총 개수 출력
System.out.println("총 개수 : " + list.size());
// 값 순회 하면서 출력
for(int i = 0; i < list.size(); i++){
System.out.println("\t" + i + " : " + list.get(i));
}
// 값 삭제
list.remove(2);
list.remove(2);
list.remove("JPA");
for(String element : list){
System.out.println("\t" + element);
}
}
}
ArrayList와 LinkedList 성능 차이 테스트
package chap11.list;
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;
public class ListPerformance {
public static void main(String[] args) {
List<String> arrayList = new ArrayList<>();
List<String> linkedList = new LinkedList<>();
long startTime;
long endTime;
startTime = System.nanoTime();
for (int i = 0; i < 10000; i++) {
arrayList.add(0, String.valueOf(i));
}
endTime = System.nanoTime();
System.out.println("ArrayList 걸린시간: " + (endTime - startTime) + "ns");
startTime = System.nanoTime();
for (int i = 0; i < 10000; i++) {
linkedList.add(0, String.valueOf(i));
}
endTime = System.nanoTime();
System.out.println("LinkedList 걸린시간: " + (endTime - startTime) + "ns");
}
}
ArrayList 걸린시간: 4295900ns
LinkedList 걸린시간: 813400ns
Set 컬렉션은 저장 순서가 유지되지 않고, 중복처리를 하고 중복인 객체는 저장하지 않는다. Set 컬렉션에는 HashSet, LinkedHashSet, TreeSet 등이 있다.
Set 컬렉션에서 공통적으로 사용 가능한 Set 인터페이스의 메소드
| 기능 | 메소드 | 설명 |
|---|---|---|
| 객체 추가 | boolean add(E e) | 주어진 객체를 저장, 객체가 성공적으로 저장되면 true를 리턴하고 중복 객체면 false를 리턴 |
| 객체 검색 | boolean contains(Object o) | 주어진 객체가 저장되어 있는지 여부 |
| isEmpty() | 컬렉션이 비어 있는지 조사 | |
| Iterator iterator() | 저장된 객체를 한 번씩 가져오는 반복자 리턴 | |
| int size() | 저장되어 있는 전체 객체 수 리턴 | |
| 객체 삭제 | void clear() | 저장된 모든 객체를 삭제 |
| boolean remove(Object o) | 주어진 객체를 삭제 |
Set 컬렉션은 저장 순서가 유지되지 않기 때문에 인덱스로 객체를 가져올 수 없음으로 인덱스로 객체를 검색해서 가져오는 메소드가 없다. 대신, 전체 객체를 대상으로 한번씩 반복해서 가져오는 반복자(iterator)를 제공한다. 반복자는 Iterator 인터페이스를 구현한 객체를 말하는데, iterator() 메소드를 호출하면 얻을 수 있다.
Set<String> set = ...;
Iterator<String> iterator = set.iterator();
Iterator인터페이스에 선언된 메소드
| 리턴 타입 | 메소드명 | 설명 |
|---|---|---|
| boolean | hasNext() | 가져올 객체가 있으면 true를 리턴하고 없으면 false를 리턴합니다 (true 가 리턴될 때 next() 메서드를 사용) |
| E | next() | 컬렉션에서 하나의 객체를 가져옵니다 |
| void | remove() | Set 컬렉션에서 객체를 제거합니다 |
// Set 컬렉션에서 String 객체들을 반복해서 하나씩 가져오는 코드
Set<String> set = ...;
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) { // 저장된 객체 수만큼 루핑
String str = iterator.next(); // String 객체 하나를 가져옴
}
// Iterator를 사용하지 않고 향상된 for문을 이용해서 전체 객체를 대상으로 반복
Set<String> set = ...;
for (String str : set) { //저장된 객체 수만큼 루핑
}
// Set 컬렉션에서 Iterator의 next() 메소드로 가져온 객체를 제거
// Iterator 메서드이지만, 실제 Set 컬렉션에서 객체가 제거됨
Set<String> set = ...;
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) { // 저장된 객체 수만큼 루핑
iterator.remove(); // 객체 제거
}
Set 인터페이스의 구현 클래스, 객체들을 순서 없이 저장하고 동일한 객체는 중복 저장하지 않는다. HashSet이 판단하는 동일한 객체란 객체를 저장하기 전에 객체의 hashCode() 메서드를 호출해서 해시 코드를 알아낸 후 이미 저장되어 있던 객체들의 해시코드와 비교한다. 동일한 해시코드가 있다면 다시 equals()메서드로 두 객체를 비교해서 true가 나오면 동일한 객체로 판단하고 중복 저장하지 않는다.
hashCode() : 객체를 식별하는 정수형 값// HashSet을 생성하기 위한 기본 생성자 호출
Set<E> set = new HashSet<E>();
ArrayList, LinkedList와 마찬가지로, 타입 파라미터 E에는 컬렉션에 저장할 객체 타입을 지정하면 된다.
// String 객체를 저장하는 HashSet
Set<String> set = new HashSet<String>();
HashSet에 String 객체를 추가, 검색, 제거하는 예제
package chap11.set;
//import java.util.Set;
//import java.util.HashSet;
//import java.util.Iterator;
import chap10.wildcard.Person;
import java.util.*;
public class HashSetExample {
public static void main(String[] args) {
Set<String> hashSet = new HashSet<>();
// 값 추가
hashSet.add("가");
hashSet.add("나");
hashSet.add("가");
// 값 검색(개수 출력, 하나씩 요소 출력)
System.out.println("총 개수 : " + hashSet.size());
// 향상된 for 문 사용 해서 출력
for(String str : hashSet){ //저장된 객체 수만큼 루핑
System.out.println("\t" + str);
}
System.out.println("====================");
Iterator<String> iterator = hashSet.iterator();
while (iterator.hasNext()){ // 저장된 객체 수만큼 루핑
String element = iterator.next(); // String 객체 하나를 가져옴
System.out.println("\t" + element);
iterator.remove(); // 값 삭제 clear도 사용 가능
}
if(hashSet.isEmpty()){
System.out.println("비어있음" + hashSet);
}
// Person이라는 객체를 같은 이름을 가지고 있지만 다른 해시코드를 가지고 있어서 각각 다른 객체로 인식되는데 하나의 객체로 인지하고 중복 체크에서 걸리기 위해서 Person클래스에 hashCode와 equals라는 object에 있는 메서드를 재정의 해준다.
// 다른 패키지
Person person1 = new Person("이름");
Person person2 = new Person("이름");
Set<Person> set = new HashSet<>();
set.add(person1);
set.add(person2);
System.out.println(set.size()); // 중복 체크해서 하나의 값만 출력 1
// 같은 패키지
// hashSet이 중복 체크를 할 수 있도록(같은 값으로 인식할 수 있도록 변경)
// 중복체크를 할 때 객체 해시 코드를 바라보지 않고 name과 age 값이 동일하다면 중복으로(같은 객체로) 볼 수 있게 변경을 위해 hashCode와 equals 메서드를 재정의 해줄 것임
Member member1 = new Member("", 30);
Member member2 = new Member("", 30);
Set<Member> memberSet = new HashSet<>();
memberSet.add(member1);
memberSet.add(member2);
System.out.println(memberSet.size()); // name, age 값이 같을 경우 객체로 취급
}
}
HashSet은 각 객체가 바라보는 hashCode와 equals를 갖고 중복 확인을 한다. 두 번 중복 삽입한 인스턴스는 내부 데이터가 동일하지만 인스턴스가 다르기 때문에 객체를 둘 다 저장하게 되는데, 동일한 내부 데이터를 중복 처리할 수 있도록 바꾸기 위해 이 Object 클래스에 있는 hashCode()와 equals() 메서드를 Override를 해주어서 인스턴스가 달라도 이름, 나이가 동일하다면 동일한 객체로 간주하여 중복 저장되지 않도록 할 수 있다.
코드
package chap11.set;
import chap10.wildcard.Person;
import java.util.*;
public class HashSetExample {
public static void main(String[] args) {
Set<String> hashSet = new HashSet<>();
hashSet.add("가");
hashSet.add("나");
hashSet.add("가");
// 다른 패키지
Person person1 = new Person("이름");
Person person2 = new Person("이름");
Set<Person> set = new HashSet<>();
set.add(person1);
set.add(person2);
System.out.println(set.size()); // 중복 체크해서 하나의 값만 출력 1
// 같은 패키지
// hashSet이 중복 체크를 할 수 있도록(같은 값으로 인식할 수 있도록 변경)
// 중복체크를 할 때 객체 해시 코드를 바라보지 않고 name과 age 값이 동일하다면 중복으로(같은 객체로) 볼 수 있게 변경을 위해 hashCode와 equals 메서드를 재정의 해줄 것임
Member member1 = new Member("", 30);
Member member2 = new Member("", 30);
Set<Member> memberSet = new HashSet<>();
memberSet.add(member1);
memberSet.add(member2);
System.out.println(memberSet.size()); // name, age 값이 같을 경우 객체로 취급
}
}
// 다른 패키지
package chap10.wildcard;
public class Person {
private String name;
public Person(String name){
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return name;
}
// hashCode 재정의
@Override
public int hashCode(){
return name.hashCode();
}
// equals 재정의
@Override
public boolean equals(Object obj){
if(obj instanceof Person){
Person person = (Person) obj;
return person.name.equals(name);
} else{
return super.equals(obj);
}
}
}
// 같은 패키지
package chap11.set;
public class Member {
private String name;
private int age;
public Member(String name, int age){
this.name = name;
this.age = age;
}
@Override
public int hashCode() {
return name.hashCode() + age;
}
@Override
public boolean equals(Object obj) {
if(obj instanceof Member){
// 이 부분만 조작
Member member = (Member) obj;
return this.name.equals(member.name) && this.age == member.age;
} else{
return super.equals(obj);
}
}
}
키(key)와 값(value)으로 구성된 객체를 저장하는 구조, 키와 값은 모두 객체이며 키는 중복될 수 없지만 값은 중복저장이 될 수 있으며, 기존에 저장되었던 키값과 동일한 키값으로 저장하면 기존의 값은 없어지고 새로운 값으로 대치된다. Map 컬렉션에는 HashMap, Hashtable, LinkedHashMap, Properties, TreeMap 등이 있다.

Map 컬렉션에서 공통으로 사용 가능한 Map 인터페이스의 메소드(. ‘Key’로 객체들을 관리하기 때문에 Key를 매개값으로 갖는 메소드가 많다.)
| 기능 | 메소드 | 설명 |
|---|---|---|
| 객체추가 | V put(K key, V value) | 주어진 키와 값을 추가, 저장되면 값을 리턴 |
| 객체검색 | boolean containsKey(Object key) | 주어진 키가 있는지 여부 |
| boolean containsValue(Object value) | 주어진 값이 있는지 여부 | |
| Set(Map.Entry<K,V>> entrySet() | 키와 값의 쌍으로 구성된 모든 Map.Entry 객체를 Set에 담아서 리턴 | |
| V get(Object key) | 주어진 키가 있는 값을 리턴 | |
| boolean isEmpty() | 컬렉션이 비어 있는지 여부 | |
| Set keySet() | 모든 키를 Set 객체에 담아서 리턴 | |
| int size() | 저장된 키의 총 개수 리턴 | |
| Collection values() | 저장된 모든 값을 Collection에 담아서 리턴 | |
| 객체삭제 | vold clear() | 모든 Map.Entry(키와 값)를 삭제 |
| V remove(Object key) | 주어진 키와 일치하는 Map.Entry를 삭제하고 값을 리턴 |
메소드의 매개변수 타입과 리턴 타입에 K, V라는 타입의 파라미터가 있는데, 이것은 Map 인터페이스가 제네릭 타입이기 때문이다. 구체적인 타입은 구현 객체를 생성할 때 결정되며 객체 추가는 put() 메소드를 사용하고, key로 객체를 찾아올 때에는get(key) 메소드를 사용합니다. 객체 삭제는 remove(key) 메소드를 사용한다.
Map 인터페이스를 구현한 대표적인 Map 컬렉션이다. HashMap을 생성하기 위해서는 키 타입과 값 타입을 파라미터로 주고 기본 생성자를 호출하면 된다.
Map<K, V> map = new HashMap<K, V>(); // K: 키 타입 파라미터, V: 값 타입 파라미터
키와 값의 타입은 Primitive type(byte, short, int, float, long, double, boolean, char)을 사용할 수 없고 클래스 및 인터페이스 타입만 가능하다.
// 키로 String 타입을 사용하고 값으로 Integer 타입을 사용하는 HashMap 생성
Map<String, Integer> map = new HashMap<String, Integer>();
HashMap사용 예제
package chap11.map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class HashMapExample {
public static void main(String[] args) {
// map 객체 추가, key, value 값 추가
Map<String, Integer> hashmap = new HashMap<>(); // HashMap : java util 에서 제공해 주는 클래스
hashmap.put("길동이", 10);
hashmap.put("길동삼", 20);
hashmap.put("길동삼", 30);
System.out.println(hashmap.size());
// 각 key, value 순회 하면서 출력
hashmap.get("길동삼"); // key 값을 알고 있다면 해당 방법으로 찾기 가능
hashmap.get("key"); // get 메서드 사용하여 검색
hashmap.getOrDefault("key", 0); // hashmap에 없는 값을 검색할 때, 빈 값이 아니라 특정 default 값을 리턴하고 싶을 때 사용
System.out.println(hashmap.get("길동삼"));
System.out.println(hashmap.get("key"));
System.out.println(hashmap.getOrDefault("key", 0));
System.out.println("=================");
// keySet() 사용
Set<String> keySet = hashmap.keySet();
for(String key : keySet) {
Integer value = hashmap.get(key); // key 값을 넣고 key에 해당하는 value(int라서 Integer) 값 가져오기
System.out.println(key + ":" + value); // 각각의 요소가 출력됨
}
System.out.println("=================");
// entrySet() 사용
Set<Map.Entry<String, Integer>> entrySet = hashmap.entrySet(); // 하나의 set 안에 여러 개의 entry로 구성 되어 있음
Iterator<Map.Entry<String, Integer>> iterator = entrySet.iterator();
while (iterator.hasNext()){
Map.Entry<String, Integer> entry = iterator.next(); // entry 한 묶음을 가져올 수 있음
System.out.println("\t" + entry.getKey() + ":" + entry.getValue());
}
}
}
HashMap과 동일한 내부 구조를 가졌다. Hashtable은 동기화된(synchronized) 메소드로 구성되어 있기 때문에 멀티 스레드가 동시에 이 메소드를 실행할 수 없고, 하나의 스레드가 실행을 완료해야 다른 스레드를 실행할 수 있다. 멀티 스레드 환경에서 안전하게 객체를 추가, 삭제할 수 있는 특징을 갖고있다. (thread safe)
Hashtable의 생성 방법은 키 타입과 값 타입을 지정하고 기본 생성자를 호출하면 된다.

Hashtable을 사용한 아이디, 비밀번호 비교 후 로그인 여부 출력 예제
package chap11.map;
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<>();
map.put("spring", "qwer"); // 실제로는 암호화 처리해야하는 pw 정보
map.put("sumer", "qwer1234");
map.put("fall", "qwer123");
map.put("winter", "qwe123");
Scanner sc = new Scanner(System.in);
// 무한으로 돌면서 값을 입력 받기
while(true){
System.out.println("아이디를 입력하세요.");
String id = sc.nextLine();
System.out.println("패스워드를 입력하세요.");
String pw = sc.nextLine();
// 실제 입력받은 id값이 맵 안에 존재하는지 확인
if(map.containsKey(id)){
System.out.println("아이디 일치");
if(map.get(id).equals(pw)){ // key 를 가져와서 pw가 일치하는지 확인
System.out.println("로그인 완료");
break;
} else{
System.out.println("패스워드가 일치하지 않습니다.");
}
} else{
System.out.println("아이디가 일치하지 않습니다.");
}
}
}
}
후입선출 (LIFO: Last In First Out) : 나중에 넣은 객체가 먼저 빠져나가는 자료구조
선입선출(First In First Out) : 먼저 넣은 객체가 먼저 빠져나가는 구조
마지막에 넣은 객체가 가장 먼저 빠지는 자료구조로 LIFO 자료구조를 구현한 클래스이다.
// Stack 객체 생성 - 저장할 객체 타입을 파라미터로 표기하고 기본 생성자 호출
Stack<E> stack = new Stack<E>();
Stack 클래스의 주요 메소드
| 리턴 타입 | 메소드 | 설명 |
|---|---|---|
| E | push(E item) | 주어진 객체를 스택에 넣는다 |
| E | peek() | 스택의 맨 위 객체를 가져온다. 객체를 스택에서 제거하지 않는다.(개수 동일) 데이터를 꺼내지는 않고 마지막에 있는 값을 리턴해준다. |
| E | pop() | 스택의 맨 위 객체를 가져오고, 객체를 스택에서 제거한다.(개수 다름) 출력 시 맨 아래에 있는 값부터 리턴된다. |
앞서 들어간 데이터가 먼저 출력이 되는 자료구조, FIFO 자료구조에서 사용되는 메소드를 정의한다.
Queue 인터페이스를 구현한 대표적인 클래스는 LinkedList 이다. LinkedList는 List 인터페이스를 구현했기 때문에 List 컬렉션이기도 하다.
// LinkedList 객체를 Queue 인터페이스 타입으로 변환
Queue<E> queue = new LinkedList<E>();
Queue 인터페이스에 정의되어 있는 메소드
| 리턴 타입 | 메소드 | 설명 |
|---|---|---|
| boolean | offer(E e) | 주어진 객체를 넣는다. |
| E | peek() | 객체 하나를 가져온다. 객체를 큐에서 제거하지 않는다. |
| E | poll() | 객체 하나를 가져온다. 객체를 큐에서 제거한다. |