프로그래밍/java

[자바 / Java] Iterator() , descendingIterator(), Comparable, Comparator

pupu91 2022. 9. 4. 14:16
반응형

Iterator() 메소드

: 컬렉션에 저장된 요소를 접근하는데 사용되는 반복자 인터페이스

  인덱스로 관리되는 컬렉션이 아닌 경우(set)에는 반복문을 사용해서 요소에 하나씩 접근할 수 없기 때문에
  인덱스를 사용하지 않고도 반복문을 사용하기 위한 목록을 만들어주는 역할

  ( Map의 경우 Set 또는 List화 시켜서 interator() 사용)

 

 

hasNext()

 : 다음 요소를 가지고 있는 경우 true, 더 이상 요소가 없는 경우 false로 반환

next()

 : 다음 요소를 반환

 

List<String> stringList = new ArrayList<>();
stringList.add("banana");
stringList.add("orange");
stringList.add("mango");
stringList.add("grape");


Iterator<String> iter = stringList.iterator();
  
    while(iter.hasNext()) {
			System.out.println(iter.next());
}

출력결과
banana
orange
mango
grape

 

반응형

 descendingIterator()

: 역순 정렬시 사용

   descendingIterator()는 ArrayList에는 없고 LinkedlList에 있기 때문에 ArrayList에 사용시 LinkedlList로 형변환 해야 함.

List<String> stringList = new ArrayList<>();
stringList.add("banana");
stringList.add("orange");
stringList.add("mango");
stringList.add("grape");

stringList = new LinkedList<>(stringList);

Iterator<String> dIter = ((LinkedList<String>)stringList).descendingIterator();
=> 타입은 아직List이기 때문에 LinkedList<String>으로 다운캐스팅 해주어야 함.

while(dIter.hasNext()) {
			System.out.println(dIter.next());
		}
        
출력결과
grape
mango
orange
banana

 

 


Comparable 과  Comparator

 

  Comparable  Comparator
패키지 java.lang java.uti
사용메소드 compareTo() compare()
정렬 기존의 정렬기준을 구현하는데 사용 그 외 다른 여러 기준으로 정렬하고자 할 때 사용
사용법
정렬하고자 하는 인스턴스에 Comparable를 상속받아 compareTo() 메소드를 오버라이딩해 기존의 정렬 기준 재정의 → 한 개의 정렬만 가능

vo 패키지 안에 필요한 정렬 기준에 맞춘 클래스들을 생성하고 Comparator를 상속받아 compare() 메소드를 오버라이딩해 기존의 정렬 기준 재정의 → 여러 개의 정렬 가능

 

 

Collections.sort()

Collections.sort(List<T> list)

: T인스턴스에 Comparable을 상속받아 compareTo 메소드 재정의를 통해 정렬 구현(단 한가지 기준의 정렬)

 

Collection.sort(List<T>list, Comparator<T> c>

: 지정한 Comparator 클래스에 의한 정렬 (여러기준 정렬)

 

 Comparator 인터페이스를 상속 받아 정렬 기준을 정해준 뒤 List의 sort() 메소드의 인자로 정렬 기준이 되는 인스턴스를   넣어주게 되면 내부적으로 우리가 오버라이딩한 메소드가 동작하여 그것을 정렬 기준으로 삼는다,

 


 

Applicaiton

package com.greedy.section01.list.run;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import com.greedy.section01.list.comparator.AscendingPrice;
import com.greedy.section01.list.dto.BookDTO;

public class Application2 {

	public static void main(String[] args) {
		
		/* 여러 권의 책 목록을 관리할 ArrayList 인스턴스 생성 */
		List<BookDTO> bookList = new ArrayList<>(); //bookDTO타입만 담는 List 생성
		
		/* 도서 정보 추가 */
		bookList.add(new BookDTO(1, "홍길동전", "허균", 50000));
		bookList.add(new BookDTO(2, "목민심서", "정약용", 30000));
		bookList.add(new BookDTO(3, "동의보감", "허준", 40000));
		bookList.add(new BookDTO(4, "삼국사기", "김부식", 46000));
		bookList.add(new BookDTO(5, "삼국유사", "일연", 58000));
		
		/* 추가 된 도서 정보 출력 */
		for(int i = 0; i < bookList.size(); i++) {
			System.out.println(bookList.get(i));
		}
		 
		/* 향상 된 for문으로 도서 정보 출력 */
		for(BookDTO book : bookList) {
			System.out.println(book);
		}
		
		/* Comparable 타입을 가지고 있는 경우에만 sort가 사용 가능하다. */
		//Collections.sort(bookList);
		
		/* 가격 순으로 오름차순 정렬 - AscendingPrice 추가 */
		/* Comparator 인터페이스를 상속 받아 정렬 기준을 정해준 뒤
		 * List의 sort() 메소드의 인자로 정렬 기준이 되는 인스턴스를 넣어주게 되면
		 * 내부적으로 우리가 오버라이딩한 메소드가 동작하여 그것을 정렬 기준으로 삼는다.
		 * */
		
        bookList.sort(new AscendingPrice()); 
		//Collections.sort(bookList, new Ascending());으로도 호출 가능
        
		System.out.println("가격 오름차순 정렬-----------------------");
		for(BookDTO book : bookList) {
			System.out.println(book);
		}
		
		/* 인터페이스를 구현할 클래스를 재사용하는 경우 AscendingPrice 클래스처럼 작성하면 되지만
		 * 한 번만 사용하기 위해서는 조금 더 간편한 방법을 이용할 수 있다.
		 * 익명클래스(Anonymous)를 이용한 방법이다.
		 * 익명 클래스는 뒤에 {}을 만들어서 마치 Comparator 인터페이스를 상속 받은 클래스인데
		 * 이름이 없다고 생각하고 사용하는 것이다.
		 * */
		bookList.sort(new Comparator<BookDTO> () {

			@Override
			public int compare(BookDTO o1, BookDTO o2) {
				/* 가격 내림차순 기준 작성
				 * 아까와는 반대로 오름차순 정렬 된 상태인 경우 순서를 바꾸야 하고
				 * 양수를 반환 해서 순서를 바꾸라는 플래그로 이용하므로 
				 * 뒤에 있는 값이 더 클 경우 양수를 반환하여 순서를 바꾸게 한다. */
				return  o2.getPrice() - o1.getPrice(); 
                //양수나오면 값바꾸고, 음수면 값 바꾸지않음, 0이면 값이 같음
			}
			
		}); 
		
		System.out.println("가격 내림차순 정렬-----------------------");
		for(BookDTO book : bookList) {
			System.out.println(book);
		}
		
		/* 제목 순 오름차순 정렬 */
		bookList.sort(new Comparator<BookDTO>() {
			
			/* 문자열은 대소 비교를 할 수 없다.
			 * 문자 배열로 변경 후 인덱스 하나 하나를 비교해서 어느 것이 더 큰 값인지 확인해야 하는데
			 * String 클래스의 compareTo() 메소드에서 이미 정의해 놓았다.
			 * */
		
			@Override
			public int compare(BookDTO o1, BookDTO o2) {
				/* 앞의 값이 더 작은 경우(즉, 바꾸지 않아도 되는 경우) 음수 반환,
				 * 같으면 0 반환,
				 * 앞의 값이 더 큰 경우 양수 반환(즉, 바꿔야 하는 경우)
				 * */
				return o1.getTitle().compareTo(o2.getTitle());
			}
			
		});
		
		System.out.println("제목 오름차순 정렬-----------------------");
		for(BookDTO book : bookList) {
			System.out.println(book);
		}
		
		/* 제목순 내림차순 정렬 */
		bookList.sort(new Comparator<BookDTO> () {

			@Override
			public int compare(BookDTO o1, BookDTO o2) {
				return o2.getTitle().compareTo(o1.getTitle());
			}
			
		});
		
		System.out.println("제목 내림차순 정렬-----------------------");
		for(BookDTO book : bookList) {
			System.out.println(book);
		}
		
		/* BookDTO implements Comparable<BookDTO> 를 작성하고 나면 메소드 호출 가능하다.
		 * 내부적인 정렬 기준이 정의 되었기 때문이다. */
		Collections.sort(bookList);
		
		System.out.println("번호 오름차순 정렬-----------------------");
		for(BookDTO book : bookList) {
			System.out.println(book);
		}
		
		/* vector의 경우 스레드 동기화 처리가 된다는 점만 다르고 ArrayList와 동일하게 동작한다.
		 * 그래서 따로 작성하지는 않을 것이다.
		 * JDK 1.0부터 사용하긴 했지만 하위 호환을 위해 남겨 놓았고 성능 문제로 현재는 사용하지 않는다.
		 * 가급적이면 ArrayList를 사용하면 된다.
		 * */

		
	}

}

 

 

 

 

Comparator를 상속받아 compare로 정렬기준 설정해주기

package com.greedy.section01.list.comparator;

import java.util.Comparator;

import com.greedy.section01.list.dto.BookDTO;

public class AscendingPrice implements Comparator<BookDTO>{ //다운캐스팅의 불편함을 해결하기 위해 미리 타입 선언

	/* Comparator 인터페이스를 상속 받으면 오버라이딩 해야 하는 메소드가 강제화 된다.
	 * 제네릭 작성 시 Object가 아닌 구체화 된 타입으로 매개변수가 선언되어 다운 캐스팅 할 필요가 없어진다.
	 * */
	@Override
	public int compare(BookDTO o1, BookDTO o2) { //o1이 앞에, o2가 뒤에 있는 값
		
		/* sort()에서 내부적으로 사용하는 메소드이다. 
		 * 비교 대상 두 인스턴스의 가격이 오름차순 정렬이 되기 위해서는 앞의 가격이 더 작은 가격이어야 하고
		 * 만약 뒤의 가격이 더 작은 경우 두 인스턴스의 순서를 바꿔야 한다.
		 * 그 때 두 값을 바꾸라는 신호로 양수를 보내주게 되면 정렬 시 순서를 바꾸는 조건으로 사용된다.
		 * */
		
		/* 양수 음수 형태로 두 비교 값이 순서를 바꿔야 하는지 알려주기 위한 용도의 변수 */
		int result = 0;
		
		if(o1.getPrice() > o2.getPrice()) {
			/* 오름차순을 위해 순서를 바꿔야 하는 경우 양수 반환 */
			result = 1; // 양수면 왼쪽이 큰 값, 값을 바꿔라 
		} else if(o1.getPrice() < o2.getPrice()) {
			/* 이미 오름차순 정렬로 되어 있는 경우 음수를 반환 */
			result = -1; // 음수면 오른쪽이 큰 값, 바꿀필요없음
		} else {
			/* 두 값이 같은 경우 0을 반환 */
			result = 0;
		}
		
		return result;
	}

	
}

 

 

 

 

 

Collections.sort(bookList)를 사용할려면 Comparable 타입을 가지고 있어야 하므로, DTO를  Comparable 상속 받는 클래스로 변경

package com.greedy.section01.list.dto;

public class BookDTO implements Comparable<BookDTO> { //compareTo사용하기 위해 Comparable상속받기

	private int number;
	private String title;
	private String author;
	private int price;
	
	public BookDTO() {}

	public BookDTO(int number, String title, String author, int price) {
		super();
		this.number = number;
		this.title = title;
		this.author = author;
		this.price = price;
	}

	public int getNumber() {
		return number;
	}

	public void setNumber(int number) {
		this.number = number;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	public int getPrice() {
		return price;
	}

	public void setPrice(int price) {
		this.price = price;
	}

	@Override
	public String toString() {
		return "BookDTO [number=" + number + ", title=" + title + ", author=" + author + ", price=" + price + "]";
	}

	@Override
	public int compareTo(BookDTO o) {
		// this 와 BookDTO o 를 비교하여 number 오름차순 정렬
		return number - o.number;
	}

}

 

반응형