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

TonyHan·2020년 11월 20일
0

20) 자바

목록 보기
18/27

5. Iterator

자바에서 어떤 Collection이 존재할때 데이터를 읽어드리는 방법은 여러가지 이지만 앞에서부터 차례대로 읽어드릴 때 사용하는 것.

public interface Iterator<E> {
	...
	boolean hasNext();
	E next();
	void remove();
}

정의는 위와 같이 되어 있다. 그래서 next를 부를 때마다 다음 원자로 넘어갈 수 있고 다음 인자가 존재하는지 화인하기 위해 hasNext 함수가 존재한다.

public interface Collection<E> {
	...
	public Iterator iterator();
	...
}

어떤 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());
}

위와 같이 그 다음원소가 있다면 계속해서 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());
		}
	}
}

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());
		}
	}
}

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]

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)

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)

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]]

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

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'));
}

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));
	}
	...
}

그렇기 때문에 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);
	}
}

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));
	}
}

분명 대문자 우선의 아스키코드 우선으로 출력이 될것이다.

그런데 우리가 원하는 것은 내림차순이라면 어떻게 해야 할까?

이것을 위해서 다음 클래스를 새롭게 선언해 준다.

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
	}
}


실재 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)); 

하지만 위의 방식은 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));
	}
}
profile
신촌거지출신개발자(시리즈 부분에 목차가 나옵니다.)

0개의 댓글