5. Iterator
자바에서 어떤 Collection이 존재할때 데이터를 읽어드리는 방법은 여러가지 이지만 앞에서부터 차례대로 읽어드릴 때 사용하는 것.
public interface Iterator<E> {
...
boolean hasNext();
E next();
void remove();
}
Plain Text
복사
정의는 위와 같이 되어 있다. 그래서 next를 부를 때마다 다음 원자로 넘어갈 수 있고 다음 인자가 존재하는지 화인하기 위해 hasNext 함수가 존재한다.
public interface Collection<E> {
...
public Iterator iterator();
...
}
Plain Text
복사
어떤 collection이 존재하면 iterator에 해당하는 interface가 호출된다.
Iterator: methods
함수는 위와 같이 제공된다. 이때 remove만 설명하면 가장 최근에 호출했던 element만 삭제된다.
사용법은 아래와 같다.
List<Integer> list = new ArrayList<Integer>();
Iterator<Integer> it = list.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
Plain Text
복사
위와 같이 그 다음원소가 있다면 계속해서 iterator 변수를 이용하여서 다음 변수로 이동하고 원하는 결과물을 출력한다.
이때 일반적으로 List<integer> 타입의 iterator을 우선적으로 사용한다. 왜냐하면 List Class는 ArrayList와 LinkedList의 상위 타입이기 때문에 나중에 ArrayList에서 LinkedList로 변경된다 하더라도 사용이 가능하기 때문이다.
Iterator: example 1
import java.util.*;
class Lecture {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
list.add("5");
// Iterator의 그 다음 원소를 계속해서 참조한다.
Iterator<String> it =list.iterator();
while(it.hasNext()) {
System.out.print(it.next());
}
}
}
Plain Text
복사
ListIterator
Iterator의 subclass로써 Iterator과의 차이점은 함수 몇가지가 추가된다는 점이다.
Iterator: example 2
import java.util.*;
class Lecture {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
list.add("5");
ListIterator<String> it = list.listIterator();
while(it.hasNext()) {
System.out.print(it.next());
}
System.out.println();
// 이 부분이 차이점으로 이전에 있던 노드를 참조할 수 있다.
ListIterator<String> it2 = list.listIterator();
while(it2.hasNext()) {
System.out.print(it2.next());
}
System.out.println();
while(it2.hasPrevious()) {
System.out.print(it2.previous());
}
}
}
Plain Text
복사
6. Arrays
array와 관련된 method들을 제공해주는 역활을 수행한다.
copyOf : copyOf는 원래의 array로 부터 성분들을 복사해서 새로운 array를 만든다.
copyOfRange : (arr, 이상, 미만)의 자료를 복사한다.
int[] arr = {0, 1, 2, 3, 4};
// arr 처음부터 arr의 크기만큼 복사하겠다.
int[] arr2 = Arrays.copyOf(arr, arr.length); // arr2 is [0, 1, 2, 3, 4]
// arr 처음부터 3개만 복사
int[] arr3 = Arrays.copyOf(arr, 3); // arr3 is [0, 1, 2]
// arr 처음부터 7개만 복사 : 비는 부분은 0으로 초기화
int[] arr4 = Arrays.copyOf(arr, 7); // arr4 is [0, 1, 2, 3, 4, 0, 0]
int[] arr5 = Arrays.copyOfRange(arr, 2, 4); // arr5 is [2, 3] (index 4 is excluded)
int[] arr6 = Arrays.copyOfRange(arr, 0, 7); // arr6 is [0, 1, 2, 3, 4, 0, 0]
Plain Text
복사
Arrays: methods
fill() : 어떠한 array를 일관된 값으로 채운다는 의미이다.
setAll() : generator function으로 만들어진 값들로 array를 채우겠다.
int[] arr = new int[5];
Arrays.fill(arr, 9); // arr is [9, 9, 9, 9, 9]
// () -> (int)(Math.random()*5)+1 : lambda experssion 형태로 압력
//()은 입력되는 것이 없다. -> 뒤쪽은 함수가 return 하는 값들이다. 여기에서는 (정수)(랜덤값*5)+1 의 랜덤값으로 반환하겠다는 의미이다.
Arrays.setAll(arr, () -> (int)(Math.random()*5)+1); // arr is [1, 5, 2, 1, 1]
// (random numbers between 1 and 5)
Plain Text
복사
sort() : 오름차순으로 데이터가 정렬된다.
binarySearch(Array, 찾는 값) : Array를 search해서 찾는 값이 존재하는지 확인하는 binarySearch 알고리즘 방식의 함수이다. 대신 사용하기 위해서는 반드시 정렬이 되어 있어야 한다.
int[] arr = {3, 2, 0, 1, 4};
int idx = Arrays.binarySearch(arr, 2); // idx = -5 (wrong result)
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
int idx = Arrays.binarySearch(arr, 2); // idx = 2 (correct result)
Plain Text
복사
toString(str) : Array를 String으로 만들어 준다.
equals(str1,str2) : 두 Array의 모든 element가 같은지 확인하다.(1차원)
int[] arr = {0, 1, 2, 3, 4};
int[][] arr2D = {{11, 12}, {21, 22}};
System.out.println(Arrays.toString(arr)); // [0, 1, 2, 3, 4]
System.out.println(Arrays.deepToString(arr2D)); // [[11, 12], [21, 22]]
Plain Text
복사
deepEquals(str1,str2) : 두 Array의 모든 element가 같은지 확인한다.(2차원)
String[][] str2D = new String[][]{{"aaa","bbb"},{"AAA","BBB"}};
String[][] str2D2 = new String[][] {{"aaa","bbb"},{"AAA","BBB"}};
System.out.println(Arrays.equals(str2D, str2D2)); // false
System.out.println(Arrays.deepEquals(str2D, str2D2)); // true
Plain Text
복사
Arrays: example
public static void main(String[] args) {
int[] arr = {0, 1, 2, 3, 4};
int[][] arr2D = {{11, 12, 13}, {21, 22, 23}};
System.out.println("arr="+Arrays.toString(arr));
System.out.println("arr2D="+Arrays.deepToString(arr2D));
// copyOf
int[] arr2 = Arrays.copyOf(arr, arr.length);
int[] arr3 = Arrays.copyOf(arr, 3);
int[] arr4 = Arrays.copyOf(arr, 7);
//copyOfRange
int[] arr5 = Arrays.copyOfRange(arr, 2, 4);
int[] arr6 = Arrays.copyOfRange(arr, 0, 7);
// toString
System.out.println("arr2="+Arrays.toString(arr2));
System.out.println("arr3="+Arrays.toString(arr3));
System.out.println("arr4="+Arrays.toString(arr4));
System.out.println("arr5="+Arrays.toString(arr5));
System.out.println("arr6="+Arrays.toString(arr6));
// fill
int[] arr7 = new int[5];
Arrays.fill(arr7, 9);
System.out.println("arr7="+Arrays.toString(arr7));
// setAll
Arrays.setAll(arr7, i -> (int)(Math.random()*6)+1);
System.out.println("arr7="+Arrays.toString(arr7));
for(int i : arr7) {
char[] graph = new char[i];
Arrays.fill(graph, '*');
System.out.println(new String(graph)+i);
}
// equals, deepEquals
String[][] str2D = new String[][]{{"aaa","bbb"},{"AAA","BBB"}};
String[][] str2D2 = new String[][]{{"aaa","bbb"},{"AAA","BBB"}};
System.out.println(Arrays.equals(str2D, str2D2));
System.out.println(Arrays.deepEquals(str2D, str2D2));
// binarySearch
char[] chArr = {'A', 'D', 'C', 'B', 'E'};
System.out.println("chArr="+Arrays.toString(chArr));
System.out.println("index of B="+Arrays.binarySearch(chArr, 'B'));
// sort + binarySearch
System.out.println("=== After sorting ===");
Arrays.sort(chArr);
System.out.println("chArr="+Arrays.toString(chArr));
System.out.println("index of B="+Arrays.binarySearch(chArr, 'B'));
}
Plain Text
복사
7. Comparable and Comparator
Comparable
Arrays나 Collection나 sort가 존재한다. 그런데 int나 float와 같은 경우 primitive trpse이기 때문에 비교가 가능해서 sort가 가능하다.
하지만 object와 같은 경우에 두 object가 비교가 불가능하기 때문에 sort가 불가능한 경우가 대다수이다.
그렇기 때문에 정리하면 성분들이 비교가 가능할때(comparable)만 가능하다.
그렇기 때문에 implements interface Comparable<T>의 타입 이 클래스는 실재로 interface Comparable을 구현한다.
Comparable: example
Comparable이라는 interface 안에는 compareTo라는 method가 존재
public final class Integer extends Number implements Comparable<Integer> {
...
public int compareTo(Integer anotherInteger) {
int thisVal = this.value;
int anotherVal = anotherInteger.value;
return (thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1));
}
...
}
Plain Text
복사
그렇기 때문에 compare을 상속받는 클래스에서는 compareTo를 구현해 주어야 한다. 내부를 살피어 보면 Integer을 상속받아서 비교를 하는 것을 확인할 수 있다.
이제 반환하는 것을 확인하면 -1이 반환된다면 thisVal이 더 작다는 것이고 만약 같다면 한 번더 비교를 해서 anotherVal이 더 크다면 1이 반환되게 된다.
// Comparable 클래스를 우선 상속하여 준다.
class Employee implements Comparable<Employee> {
private String name;
private int salary;
public Employee(String name, int salary) { this.name = name; this.salary = salary; }
public String getName() { return this.name; }
public int getSalary() { return this.salary; }
// 여기에서도 compareTo를 define 해준 것을 확인 할 수 있다.
public int compareTo(Employee e) {
if(this.salary > e.getSalary()) return -1;
if(this.salary < e.getSalary()) return 1;
return this.name.compareTo(e.getName());
}
public String toString() { return this.name + " " + this.salary; }
}
public class Lecture {
public static void main(String[] args) {
ArrayList<Employee> emplist = new ArrayList<Employee>();
emplist.add(new Employee("Peter", 50000));
emplist.add(new Employee("John", 100000));
emplist.add(new Employee("Robert", 100000));
// 여기에서 정렬을 하게 된다면 salary가 더 높은 사람 그 다음으로 이름을 비교할 것으로 예상이 된다.
System.out.println(emplist);
Collections.sort(emplist);
System.out.println(emplist);
}
}
Plain Text
복사
Comparator
다른 방법으로 sort를 하기 원한다면 Comparator을 사용한다.
만약 아래 예시처럼 Arrays.sort를 사용하게 된다면 어떻게 될까?
public class Lecture {
public static void main(String[] args) {
String[] strArr = {"lion", "DOG", "TIGER", "cat"};
System.out.println("strArr = " + Arrays.toString(strArr));
Arrays.sort(strArr);
System.out.println("strArr = " + Arrays.toString(strArr));
}
}
Plain Text
복사
분명 대문자 우선의 아스키코드 우선으로 출력이 될것이다.
그런데 우리가 원하는 것은 내림차순이라면 어떻게 해야 할까?
이것을 위해서 다음 클래스를 새롭게 선언해 준다.
class Descending<T> implements Comparator<T> {
//o1과 o2를 비교하는 함수
public int compare(T o1, T o2) {
//Comparable의 subClass인지 확인후 type 변환
if(o1 instanceof Comparable && o2 instanceof Comparable) {
Comparable c1 = (Comparable)o1;
Comparable c2 = (Comparable)o2;
//내림차순으로 바꾸기
return c1.compareTo(c2) * -1; // reverse order
}
return -1; // undefined
}
}
Plain Text
복사
실재 Comparator은 다음과 같이 구현이 되어 있다.
public static final Comparator<String> CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator();
private static class CaseInsensitiveComparator implements Comparator<String>, java.io.Serializable {
private static final long serialVersionUID = 8575799808933029326L;
public int compare(String s1, String s2) {
byte v1[] = s1.value;
byte v2[] = s2.value;
if(s1.coder() == s2.coder()) {
// compareToCI : Case를 무시하고 compare하는 것을 의미
return s1.isLatin1() ? StringLatin1.compareToCI(v1, v2) : StringUTF16.compareToCI(v1, v2);
}
return s1.isLatin() ? StringLatin1.compareToCI_UTF16(v1, v2) : StringUTF16.compareToCI_Latin1(v1, v2);
}
private Object readResolve() { return CASE_INSENSITIVE_ORDER; }
}
String[] strArr = {"lion", "DOG", "TIGER", "cat"};
//아래와 같이 sort를 할때 CASE_INSENSITIVE_ORDER을 사용하게 되면
//CASE를 무시하게 되고 내림차순으로 정렬되게 된다.
Arrays.sort(strArr, String.CASE_INSENSITIVE_ORDER);
System.out.println("strArr = " + Arrays.toString(strArr));
Plain Text
복사
하지만 위의 방식은 raw타입을 사용하기 때문에 예외가 생길 수 있다. 그래서 타입을 정해주는 다음과 같은 형식으로 코드를 짜줄 필요가 있다.
class Descending implements Comparator<String>{
public int compare(String s1,String s2) {
return s1.compareTo(s2)*2;
}
}
public class Ex18_04 {
public static void main(String[] args) {
String[] strArr = { "lion", "DOG", "TIGER", "cat" };
System.out.println("strArr = " + Arrays.toString(strArr));
Arrays.sort(strArr);
System.out.println("strArr = " + Arrays.toString(strArr));
Arrays.sort(strArr, new Descending());
System.out.println("strArr = " + Arrays.toString(strArr));
}
}
Plain Text
복사