Search
Duplicate

자바를 자바 18 (Collection Framework (3)) : Iterator, Array, Comparable, Comparator

간단소개
팔만코딩경 컨트리뷰터
ContributorNotionAccount
주제 / 분류
Java
Scrap
태그
9 more properties

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
복사