[이것이 자바다] 15장 정리
자바에서 사용할 수 있는 다양한 컬렉션 자료구조를 익힐 수 있는 예제들이 포함되어 있습니다. ArrayList, LinkedList, HashSet, HashMap, TreeSet 등의 자료구조와 관련된 핵심 키워드와 사용법을 확인할 수 있습니다.
Jan 18, 2024
Contents
Board.javaBoardExam.java핵심 키워드LinkedListExam.java핵심 키워드HashSetExam.java핵심 키워드Member.javaMemberExam.java핵심 키워드HashSetExam.java핵심 키워드HashMapExam.java핵심 키워드TreeSetExam.java핵심 키워드TreeMapExam.java핵심 키워드Person.javaPersonExam.java핵심 키워드Fruit.javaFruitComparator .javaFruitExam.java핵심 키워드Coin.javaStackExam.java핵심 키워드ImmutableExam.java핵심 키워드연습문제 7번.java연습문제 8번.java연습문제 9번.java연습문제 10번.java결론Board.java
package ch15;
public class Board {
private String title;
private String contents;
private String writer;
public Board(String title, String contents, String writer) {
this.title = title;
this.contents = contents;
this.writer = writer;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@Override
public String toString() {
return "Board [title=" + title + ", contents=" + contents + ", writer=" + writer + "]";
}
public String getContents() {
return contents;
}
public void setContents(String contents) {
this.contents = contents;
}
public String getWriter() {
return writer;
}
public void setWriter(String writer) {
this.writer = writer;
}
}
BoardExam.java
package ch15;
import java.util.ArrayList;
import java.util.List;
public class BoardExam {
public static void main(String[] args) {
List<Board> list = new ArrayList<>();
list.add(new Board("제목 1", "내용 1", "글쓴이 1"));
list.add(new Board("제목 2", "내용 2", "글쓴이 2"));
list.add(new Board("제목 3", "내용 3", "글쓴이 3"));
list.add(new Board("제목 4", "내용 4", "글쓴이 4"));
list.add(new Board("제목 5", "내용 5", "글쓴이 5"));
int size = list.size();
System.out.println("총 글 수: " + size);
// for (int i = 0; i < size; i++) {
// System.out.println("요소 " + i + "번: " + list.get(i));
// }
for(Board b: list) { // toString override가능
System.out.println(b.toString());
}
}
}
핵심 키워드
- List 컬렉션을 이용해서 객체를 저장할 수 있다.
- List 컬렉션은 객체 자체를 저장하는 것이 아니라 객체의 번지를 저장한다.
- 또한 동일한 객체를 중복 저장할 수 있으며, 이 경우에는 동일한 번지가 저장된다.
LinkedListExam.java
package ch15;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class LinkedListExam {
public static void main(String[] args) {
List<String> list1 = new ArrayList<>(); // 내부에서 형변환이 이뤄질 수 있게 list로 선언
long startTime = System.nanoTime();
for (int i = 0; i < 100000; i++) {
list1.add(0, String.valueOf(i));
}
System.out.println("ArrayList 걸린 시간: " + (double) (System.nanoTime() - startTime) / 1000000000 + "초");
list1 = new LinkedList<>();
startTime = System.nanoTime();
for (int i = 0; i < 100000; i++) {
list1.add(0, String.valueOf(i));
}
System.out.println("LinkedList 걸린 시간: " + (double) (System.nanoTime() - startTime) / 1000000000 + "초");
}
}
핵심 키워드
- LinkedList는 ArrayList와 사용법은 동일하지만 내부 구조는 완전히 다르다. ArrayList는 내부 배열에 객체를 저장하지만, LinkedList는 인접 객체를 체인처럼 연결해서 관리한다.
- 따라서 LinkedList는 특정 위치에서 객체를 삽입하거나 삭제하면 바로 앞 뒤 링크만 변경하면 되므로 빈번한 객체 삭제와 삽입이 일어나는 곳에서는 ArrayList보다 좋은 성능을 발휘한다.
HashSetExam.java
package ch15;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class HashSetExam {
public static void main(String[] args) {
Set<String> set = new HashSet<String>();
set.add("Java");
set.add("JDBC");
set.add("JSP");
set.add("Java");
set.add("Spring");
System.out.println(set.size());
Iterator<String> iterator = set.iterator(); // 또는 iterator 사용
while(iterator.hasNext()) {
String s = iterator.next();
if(s.equals("JDBC")) {
iterator.remove();
}
}
for(String s: set) { // 순서대로 접근해서 꺼내오기 불가능하므로 for each문 사용
System.out.println(s);
}
}
}
핵심 키워드
- HashSet은 동일한 객체는 중복 저장하지 않는다.
- 동일한 객체란 hashCode()의 리턴값이 같고, equals()의 리턴값이 같을 경우를 말한다.
Member.java
package ch15;
public class Member {
String name;
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 target) {
return target.name.equals(this.name) && (target.age == this.age);
} else {
return false;
}
}
}
MemberExam.java
package ch15;
import java.util.HashSet;
import java.util.Set;
public class MemberExam {
public static void main(String[] args) {
Set<Member> set = new HashSet<>();
Member m1 = new Member("홍길동", 30);
Member m2 = new Member("홍길동", 30);
set.add(m1); // 인스턴스는 다르지만 리터럴은 같다. 따라서 같은 번지를 참조한다.
set.add(m2);
System.out.println(m1.name.hashCode() + " " + m1.age);
System.out.println(m2.name.hashCode() + " " + m2.age);
System.out.println(m1.equals(m2));
System.out.println(set.size());
}
}
핵심 키워드
- 인스턴스가 달라도 리터럴이 같으면 같은 번지를 참조하게 된다. 따라서 HashSet에 객체를 저장할 때 객체가 중복 저장되지 않는다.
HashSetExam.java
package ch15;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class HashSetExam {
public static void main(String[] args) {
Set<String> set = new HashSet<String>();
set.add("Java");
set.add("JDBC");
set.add("JSP");
set.add("Java");
set.add("Spring");
System.out.println(set.size());
Iterator<String> iterator = set.iterator(); // 또는 iterator 사용
while(iterator.hasNext()) {
String s = iterator.next();
if(s.equals("JDBC")) {
iterator.remove();
}
}
for(String s: set) { // 순서대로 접근해서 꺼내오기 불가능하므로 for each문 사용
System.out.println(s);
}
}
}
핵심 키워드
- Set 컬렉션은 인덱스로 접근해서 객체를 가져올 수 없으므로 for each 문을 통해 객체를 한개씩 반복해서 가져온다.
HashMapExam.java
package ch15;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class HashMapExam {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("신용권", 85);
map.put("홍길동", 90);
map.put("동장군", 80);
map.put("홍길동", 95); // value를 덮어쓴것이다.
System.out.println("총 엔트리 수: " + map.size());
String key = "홍길동";
int value = map.get(key);
System.out.println(key + ": " + value);
String key2 = "김지영"; // 어지간하면 get보다 getOrDefault를 사용할 것
int value2 = map.getOrDefault(key2, 0); // 키값으로 검색이 안된다며 디폴드값으로 value를 리턴
System.out.println(key2 + ": " + value2);
// Set<String> keySet = map.keySet();
// for(String s: keySet) {
// System.out.println(s);
// }
//
// for(Integer i : map.values()) { // 보통 이렇게 더 많이 쓴다.
// System.out.println(i);
// }
//
// for(Entry<String, Integer> e : map.entrySet()) {
// System.out.println(e.getKey()+" "+e.getValue());
// }
}
}
핵심 키워드
- HashMap 컬렉션은 키로 사용할 객체가 hashCode() 메소드의 리턴값이 같고 equals() 메소드가 true를 리턴할 경우, 동일 키로 보고 중복 저장을 허용하지 않는다.
- HashMap 컬렉션에서 key가 같고 value가 다른 값을 put 하면 value를 덮어쓴다.
- .getOrDefault() 메소드를 사용하면 key값을 기준으로 value를 검색할 수 있다.
TreeSetExam.java
package ch15;
import java.util.Iterator;
import java.util.NavigableSet;
import java.util.TreeSet;
public class TreeSetExam {
public static void main(String[] args) {
TreeSet<Integer> scores = new TreeSet<>();
scores.add(80);
scores.add(98);
scores.add(75);
scores.add(95);
scores.add(32);
scores.add(78);
for (Integer i : scores) {
System.out.print(i + ", ");
}
System.out.println();
System.out.println(scores.first()); // 가장 작은
System.out.println(scores.last()); // 가장 큰
System.out.println(scores.lower(95)); // 미만 중 첫번째
System.out.println(scores.higher(95)); // 초과 중 첫번째
System.out.println(scores.floor(95)); // 이하 중 첫번째
System.out.println(scores.ceiling(80)); // 이상 중 첫번째
// System.out.println(scores.pollFirst()); // 첫번째를 꺼내옴
// System.out.println(scores.pollLast());
// for (Integer i : scores) {
// System.out.print(i + ", ");
// }
// Iterator<Integer> iterator = scores.descendingIterator(); // 이터레이터는 잘 안쓴다.
// while(iterator.hasNext()) {
// System.out.print(iterator.next() + ", ");
// }
// System.out.println();
for (Integer i : scores.descendingSet()) { // 보통 이렇게 사용.
System.out.print(i + ", ");
}
System.out.println();
for (Integer i : scores.headSet(75, true)) { // 이하 모든 값 (디폴트: false)
System.out.print(i + ", ");
}
System.out.println();
for (Integer i : scores.tailSet(75, true)) { // 이상 모든 값 (디폴트: false)
System.out.print(i + ", ");
}
System.out.println();
for (Integer i : scores.subSet(78, true, 98, true)) { // 사잇값 (시작-디폴트: true)
System.out.print(i + ", ");
}
System.out.println();
}
}
핵심 키워드
- TreeSet은 이진 트리를 기반으로 한 Set 컬렉션이다. TreeSet에 객체를 저장하면 부모 노드의 객체와 비교해서 낮은 것은 왼쪽 자식 노드에, 높은 것은 오른쪽 자식 노드에 저장한다.
- 검색 관련 메소드가 TreeSet에만 정의되어 있기 때문에 TreeSet 컬렉션을 생성할 때는 다음과 같이 작성한다.
- TreeSet<E> treeset = new TreeSet<>();
TreeMapExam.java
package ch15;
import java.util.Map.Entry;
import java.util.TreeMap;
public class TreeMapExam {
public static void main(String[] args) {
TreeMap<String, Integer> treeMap = new TreeMap<>();
treeMap.put("apple", 10);
treeMap.put("forever", 60);
treeMap.put("description", 40);
treeMap.put("ever", 50);
treeMap.put("zoo", 50);
treeMap.put("base", 20);
treeMap.put("guess", 70);
treeMap.put("cherry", 70);
for (Entry<String, Integer> e : treeMap.entrySet()) {
System.out.println(e.getKey() + "-" + e.getValue());
}
Entry<String, Integer> e = treeMap.firstEntry();
System.out.println(e.getKey() + "-" + e.getValue());
Entry<String, Integer> e2 = treeMap.higherEntry("h");
System.out.println(e2.getKey() + "-" + e2.getValue());
}
}
핵심 키워드
- TreeMap은 이진 트리를 기반으로 한 Map 컬렉션이다. TreeSet과의 차이점은 키와 값이 저장된 Entry를 저장한다는 것이다.
Person.java
package ch15;
public class Person implements Comparable<Person> {
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Person o) { // 오름차순으로 정렬된다.
// if (age < o.age)
// return -1;
// else if (age == o.age)
// return 0;
// else
// return 1;
return this.age - o.age; // 한줄로 줄일 수 있다.
}
}
PersonExam.java
package ch15;
import java.util.TreeSet;
public class PersonExam {
public static void main(String[] args) {
TreeSet<Person> treeSet = new TreeSet<>();
treeSet.add(new Person("홍길동", 45));
treeSet.add(new Person("김자바", 25));
treeSet.add(new Person("박지원", 31));
for (Person p : treeSet) {
System.out.println(p.name + ", " + p.age);
}
}
}
핵심 키워드
- TreeSet에 저장되는 객체와 TreeMap에 저장되는 키 객체는 Comparable 인터페이스의 구현을 통해 저장과 동시에 정렬된다.
Fruit.java
package ch15;
public class Fruit {
public String name;
public int price;
public Fruit(String name, int price) {
this.name = name;
this.price = price;
}
}
FruitComparator .java
package ch15;
import java.util.Comparator;
public class FruitComparator implements Comparator<Fruit> {
@Override
public int compare(Fruit o1, Fruit o2) {
return o2.price - o1.price;
}
}
FruitExam.java
package ch15;
import java.util.Comparator;
import java.util.TreeSet;
public class FruitExam {
public static void main(String[] args) {
// TreeSet<Fruit> ts = new TreeSet<>(new FruitComparator());
// TreeSet<Fruit> ts = new TreeSet<>(new Comparator<Fruit>() { // 익명 객체로 구현 가능
// @Override
// public int compare(Fruit o1, Fruit o2) {
// return o2.price - o1.price;
// }
// });
TreeSet<Fruit> ts = new TreeSet<>((o1, o2) -> o1.price - o2.price); // 람다식으로도 구현 가능
ts.add(new Fruit("포도", 3000));
ts.add(new Fruit("수박", 10000));
ts.add(new Fruit("딸기", 6000));
for (Fruit f : ts) {
System.out.println(f.name + ", " + f.price);
}
}
}
핵심 키워드
- 비교 기능이 없는 Comparable 비구현 객체를 저장하고 싶다면 TreeMap과 TreeSet을 생성할 때 Comparator을 다음과 같이 제공해야 한다.
- TreeSet<Fruit> ts = new TreeSet<>(new FruitComparator()); // 클래스를 생성
- TreeSet<Fruit> ts = new TreeSet<>(new Comparator<Fruit>() {}); // 익명 구현 객체
- TreeSet<Fruit> ts = new TreeSet<>((o1, o2) -> o1.price - o2.price); // 람다식
Coin.java
package ch15;
public class Coin {
private int value;
public Coin(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
StackExam.java
package ch15;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
public class StackExam {
public static void main(String[] args) {
Stack<Coin> st = new Stack<>();
st.push(new Coin(100));
st.push(new Coin(50));
st.push(new Coin(500));
st.push(new Coin(10));
st.peek();
while (!st.isEmpty()) {
Coin coin = st.pop();
System.out.println(coin.getValue());
}
Queue<Coin> q = new LinkedList<>();
q.offer(new Coin(100));
q.offer(new Coin(50));
q.offer(new Coin(500));
q.offer(new Coin(10));
q.peek();
System.out.println();
while (!q.isEmpty()) {
Coin coin = q.poll();
System.out.println(coin.getValue());
}
}
}
핵심 키워드
- Stack 클래스는 LIFO 자료구조를 구현한 클래스이다.
- Queue 인터페이스는 FIFO 자료구조에서 사용되는 메소드를 정의하고 있다. Queue 인터페이스를 구현한 대표적인 클래스는 LinkedList이다.
- LIFO는 나중에 넣은 객체가 먼저 빠져나가는 구조이다.
- FIFO는 먼저 넣은 객체가 먼저 빠져나가는 구조이다.
ImmutableExam.java
package ch15;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class ImmutableExam {
public static void main(String[] args) {
List<String> l1 = List.of("A", "B", "C"); // immutable
Set<String> s1 = Set.of("A", "B", "C"); // immutable
Map<Integer, String> m1 = Map.of( // immutable
1, "A",
2, "B",
3, "C");
List<String> l2 = new ArrayList<>();
l2.add("A");
l2.add("B");
l2.add("C");
List<String> l3 = List.copyOf(l2); // immutable
String[] arr = {"A", "B", "C"};
List<String> l4 = Arrays.asList(arr); // immutable
List<String> l5 = new ArrayList<>(); // mutable
for(String s: arr) {
l5.add(s);
}
}
}
핵심 키워드
- List.of(), Set.of(), Map.of(), List.copyOf(), Arrays.asList() 메소드를 통해 요소를 추가, 삭제할 수 없는 컬렉션을 만들 수 있다.
연습문제 7번.java
package ch15.example;
import java.util.ArrayList;
import java.util.List;
public class BoardDao {
public List<Board> getBoardList() {
List<Board> list = new ArrayList<Board>();
list.add(new Board("제목1","내용1"));
list.add(new Board("제목2","내용2"));
list.add(new Board("제목3","내용3"));
return list;
}
}
연습문제 8번.java
package ch15.example;
public class Student {
public int studentNum;
public String name;
public Student(int studentNum, String name) {
super();
this.studentNum = studentNum;
this.name = name;
}
@Override
public int hashCode() {
return this.studentNum;
}
@Override
public boolean equals(Object obj) {
if(obj instanceof Student s) {
return s.studentNum == this.studentNum;
}
return false;
}
}
연습문제 9번.java
package ch15.example;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MapExample {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("blue", 96);
map.put("hong", 86);
map.put("white", 92);
String name = null;
int maxScore = 0;
int totalScore = 0;
Set<Map.Entry<String, Integer>> EntrySet = map.entrySet();
for (Map.Entry<String, Integer> entry : EntrySet) {
if (entry.getValue() > maxScore) {
name = entry.getKey();
maxScore = entry.getValue();
}
totalScore += entry.getValue();
}
System.out.println("평균 점수: " + totalScore / map.size());
System.out.println("최고 점수: " + maxScore);
System.out.println("최고 점수를 받은 아이디: " + name);
}
}
연습문제 10번.java
package ch15.example;
public class Student implements Comparable<Student>{
public String id;
public int score;
@Override
public int compareTo(Student o) {
return this.score - o.score;
}
}
결론
해당 문제를 풀면서 자바에서 사용할 수 있는 여러 컬렉션 자료구조를 익힐 수 있었다.
Share article