[이것이 자바다] 15장 정리

자바에서 사용할 수 있는 다양한 컬렉션 자료구조를 익힐 수 있는 예제들이 포함되어 있습니다. ArrayList, LinkedList, HashSet, HashMap, TreeSet 등의 자료구조와 관련된 핵심 키워드와 사용법을 확인할 수 있습니다.
Jan 18, 2024
[이것이 자바다] 15장 정리

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

More articles

See more posts
RSSPowered by inblog