
드디어
자바 중급 2 강의를 완강했다....
이제 Spring 으로 넘어간다.
갈 길이 멀구나 ⛰️....😂
예전부터 있었던 강박(?) 인데 복습을 할 때 전부 하나하나 다 내가 말로 설명할 수 있을 정도로 되지 않으면 복습은 제대로 한거 같지 않아서 공부하기 힘들어하는 경우가 많았다.
하지만 이제는 안다. 당연히 한 번 복습했다고 다 기억하면 좋겠지만‼️ 보통은 여러번 복습을 해서 설명할 수 있을 정도로 익혀나간다는 것을.
그러니까 너무 강박을 가지고 무겁게 공부하지 말자.
한 번에 모든 걸 하려고 하지 말자 🐥💛
자료구조의 요소를 순회할 때 사용하는 인터페이스
package collection.iterable;
import java.util.Iterator;
public class MyArrayMain {
public static void main(String[] args) {
MyArray myArray = new MyArray(new int[]{1, 2, 3, 4});
Iterator<Integer> iterator = myArray.iterator();
System.out.println("iterator 사용");
while (iterator.hasNext()) {
Integer value = iterator.next();
System.out.println("value = " + value);
}
}
}
순회의 기능을 사용하려는 타입에 구현되는 인터페이스다. 이 인터페이스에는 Iterator 를 사용하는 iterator() 라는 메서드가 정의되어있다. 그래서 이 인터페이스를 순회의 인증표 라고 생각하면 된다.
package collection.iterable;
import java.util.Iterator;
public class MyArray implements Iterable<Integer> {
private int[] numbers;
public MyArray(int[] numbers) {
this.numbers = numbers;
}
@Override
public Iterator<Integer> iterator() {
return new MyArrayIterator(numbers);
}
}
자바에서 제공하는 "컬렉션"들은 모두 Iterable 이 구현되어있다. 배열은 JVM에서 특별 취급해서 없이 순회 가능하다.
순회는 여러 개일 때만 의미가 있기 때문이다. 데이터가 하나 있는 값을 순회하는 건 말이 안된다. 그래서 자바는 하나짜리 값은 순회 불가능하게 하고, 여러 개를 담은 것은 이라는 표식으로 Iterable 을 붙여 사용가능하게하는 것이다.
순회에 사용되는 메서드들을 가지고 있는 실질적인 반복자 인터페이스다. hasNext(), next() 메서드를 통해서 Iterable 이 구현된 모든 타입을 순회할 수 있다.
대부분은 직접 구현하지 않고 return list.iterator(); 즉, 자바 컬렉션이 제공(List, Set, Map) 하는 걸 사용한다.
class Tree {
Node root;
}
class CustomOrder implements Iterable<Item> {
private List<Item> items;
}
보통 이 2가지 경우에만 직접 구현한다.
향상된 for문은 객체를 순회하는 기능을 가지고 있다. 이 순회 문법을 사용하기 위해서는 배열이거나, Iterable 을 구현한 타입이어야 한다. 그렇지 않으면 컴파일 오류가 발생한다.
내가 만든 타입에 항상 Iterable을 붙이기 ❌
내가 만든 타입이 컬렉션을 가질 때 Iterable 구현하기 ⭕️
📌 순회 방법
1. 컬렉션이 직접 순회
2. 감싼 타입이 대신 순회 ➡️ 내부 컬렉션을 숨기고 for-each 로 순회가능하게 만듬.
class StudentGroup implements Iterable<Student> {
private List<Student> students;
}
(자료구조 안의 타입은 뭐든 상관 없음)
이 메서드를 보면서 왜 매개변수를 저 두 개로 만들어서 받는 걸로 설정했는지, 목적이 뭔지 이해할 수가 없었다.
private static void printAll(Iterator<Integer> iterator) {
System.out.println("iterator = " + iterator.getClass());
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
private static void foreach(Iterable<Integer> iterable) {
System.out.println("iterable = " + iterable.getClass());
for (Integer i : iterable) {
System.out.println(i);
}
}
Iterator ver.
Iterator<Integer> it = list.iterator();
printAll(it);
printAll(it); // ❌ 두 번째는 안 됨
현재 위치(currentIndex)를 기억하는 객체라서 한번 끝까지 돌면 다시 돌아갈 방법이 없다. Iterator 안에는 '지금 몇 번째에 있는지, 다음에 꺼낼 게 뭔지' 가 들어있다. 끝에 도달하면 it.hasNext() == false 가 된다. 되돌아 가는 기능은 없다.
Iterable ver.
foreach(list);
foreach(list); // ⭕ 항상 됨
두 인터페이스의 차이점을 보여주기 위해 따로 뽑은 코드다. Iterator 은 소모품이고 Iterable 은 재사용 가능한 원본이다. 실무에서는 특별한 경우가 아닌 이상, Iterable 타입의 printAll() 만 사용하면 된다.
'순회할 수 있는 대상'과 '지금 순회중인 상태'는 역할이 완전 다르기 때문에 인터페이스를 둘로 나눴다. 하나로 만들면 재사용이 어려워지고 파일/네트워크/스크림 같은 데이터에 사용이 불가능하다.
자료구조의 데이터를 정렬할 때 사용하는 인터페이스다. 순서가 있는 자료구조에서 사용이 가능하다. List, Map 처럼 순서가 있으면 사용가능 하지만 Set 처럼 순서가 유효하지 않은 경우에는 사용할 수 없다.
'정렬을 할 수 있는 상태' 를 표시하는 역할을 하는 인터페이스다.
package collection.compare;
public class MyUser implements Comparable<MyUser> {
private String id;
private int age;
public MyUser(String id, int age) {
this.id = id;
this.age = age;
}
public String getId() {
return id;
}
public int getAge() {
return age;
}
@Override
public int compareTo(MyUser o) {
return this.age < o.age ? -1 : (this.age == o.age ? 0 : 1);
}
@Override
public String toString() {
return "MyUser{" +
"id='" + id + '\'' +
", age=" + age +
'}';
}
}
➡️ compareTo() : 객체 안의 정렬 기준 메서드로 고정된 기준을 객체가 직접 가지고 있다.
🚨 순회는 표준방식이 다 갖춰져 있어서 어떤 객체든 이 방식으로만 하면 순회가 가능하도록 표준화 했지만, 정렬은 "이 객체는 정렬 가능하다" 라는 공식적인 표식 인터페이스와 문법을 만들기에 그 규칙이 너무 다양해 표준화가 어렵다. 그래서 방식을 사용자가 정하고 그에 대한 도구만 제공한다.
Collections.sort(list, comparator);⬆️ 이렇게 함수만 제공
사용자가 정하는 정렬 방식을 생성하는 인터페이스다.
package collection.compare;
import java.util.Comparator;
public class IdComparator implements Comparator<MyUser> {
@Override
public int compare(MyUser o1, MyUser o2) {
return o1.getId().compareTo(o2.getId());
}
}
➡️ compare() : 임시 기준을 외부에서 제공하는 메서드다.
- 항상 하나로 고정 : compareTo()
- 상황마다 바뀌면 : compare()
(✔️ 실무에서는 Comparator + compare() 가 훨씬 유연함)
package collection.compare;
import java.util.LinkedList;
import java.util.List;
public class SortMain4 {
public static void main(String[] args) {
MyUser myUser1 = new MyUser("a", 30);
MyUser myUser2 = new MyUser("b", 20);
MyUser myUser3 = new MyUser("c", 10);
List<MyUser> list = new LinkedList<>();
list.add(myUser1);
list.add(myUser2);
list.add(myUser3);
System.out.println("기본 데이터");
System.out.println(list);
System.out.println("Comparable 기본 정렬");
list.sort(null);
// Collections.sort(list);
System.out.println(list);
System.out.println("IdComparator 정렬");
list.sort(new IdComparator());
// Collections.sort(list,new IdComparator());
System.out.println(list);
}
}
➡️ sort() : 순서가 있는 컬렉션을 정렬해주는 메서드다.
*list.sort(null) ➡️ 기본 정렬을 사용하려면 null을 넣으면 된다.
