컬렉션 기반 알고리즘 Comparator<T>(정렬,찾기), binarySearch(찾기), copy(복사)

gustjtmd·2022년 1월 11일
0

Java

목록 보기
26/40

정렬 Comparator<'T'> 기반

  • 들어가기 앞서 <? extends T>, <? super T>에 대해서 복습해보자.
<? extends T> -- 상한 제한 T이거나 T를 상속하는 클래스들만 가능하다.
(T이거나 T의 자식 클래스들) (꺼내는 것 Get만 가능)

<? super T>   -- 하한 제한 T이거나 T가 상속하는 클래스들만 가능하다.
(T이거나 T의 부모 클래스들) (넣는것 Set만 가능)
Collections 클래스에는 다음 sort 메소드도 정의되어 있다.
이는 호출시 정렬의 기준을 결정할 수 있는 형태로 정의된 메소드이다.

public static <T> void sort(List<T> list, Comparator<? super T> c)

그리고 이번에는 매개변수 선언에 <? super T>가 있으므로 다음과 같이 판단할 수 있다.
" 매개변수 c를 대상으로는 T형 인스턴스를 넣는(전달하는(Set)) 메소드 호출만 OK.
예제를 통해서 <? super T> 선언이 주는 두번째 의미를 확인해보자.

class Car{
    protected int disp;
    public Car(int d){disp = d;}

    @Override
    public String toString(){return "cc: " +disp;}
}

//Car의 정렬을 위한 클래스
class Carcomp implements Comparator<Car> {
    @Override
    public int compare(Car o1, Car o2){return o1.disp - o2.disp;}
}

class Ecar extends Car{
    private int battery;

    public Ecar(int d, int b){
        super(d);
        battery = b;
    }
    @Override
    public String toString(){return "cc: " + disp +" ba : " +battery;}
}

public class CarComparator {
    public static void main(String[] args) {
        List<Car> clist = new ArrayList<>();
        clist.add(new Car(1800));
        clist.add(new Car(1200));
        clist.add(new Car(3000));

        List<Ecar> elist = new ArrayList<>();
        elist.add(new Ecar(3000,55));
        elist.add(new Ecar(1800,87));
        elist.add(new Ecar(1200,99));

        Carcomp comp = new Carcomp();

        //각각 정렬
        Collections.sort(clist,comp);
        Collections.sort(elist,comp);   //이 문장의 핵심

        for(Iterator<Car3> itr = clist.iterator(); itr.hasNext();)
            System.out.println(itr.next().toString() + '\t');
        System.out.println();
        for(Iterator<Ecar3> itr = elist.iterator(); itr.hasNext();)
            System.out.println(itr.next().toString() + '\t');

    }
}
---------------------------------------------------------------------
cc: 1200	
cc: 1800	
cc: 3000	

cc: 1200 ba : 99	
cc: 1800 ba : 87	
cc: 3000 ba : 55

이는 sort 메소드의 두번째 매개변수 타입이 Comparator<T>가 아닌
Comparator<? super T>이기에 가능한 일이다.


찾기 binarySearch

리스트 자료구조를 기반으로 특정 인스턴스를 찾을때 사용할수 있는 메소드가 
Collections 클래스에 다음과 같이 정의되어 있다.
public static
<T> int binarySearch(List<? extends Comparable<? superT>> list, T key)
-> list에서 key를 찾아 그 인덱스 값 반환 못찾으면 음의 정수 반환

풀어서 읽어보자

public static <T> int binarySearch(List<?> list, T key)
"첫 번째 인자로 List<E> 인스턴스는 무엇이든 올 수 있다.

public static
<T> int binarySearch(List<? extends Comparable<? superT>> list, T key)

"첫 번째 인자로 List<E> 인스턴스는 무엇이든 올 수 있다."
"단 이때 E는 Comparable<T>를 구현해야 한다."
---------------------------------------------------------------------
예제를 통해 확인해보자
public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Box");
        list.add("Robot");
        list.add("Apple");

        Collections.sort(list); //정렬
        int idx = Collections.binarySearch(list, "Robot");   //출력
        System.out.println(list.get(idx));  //탐색의 결과 출력
---------------------------------------------------------------------
Robot

찾기 : Comparator<'T'> 기반

public static <T>
int binarySearch(List<? extends T>list,T key,Comparator<?superT> c
-> list에서 key를 찾는데 c의 기준을 적용하여 찾는다.

이 메소드도 한눈에 들어오지 않는다면 다음과 같이 줄여놓고 이해하자.

public static<T> 
int binarySearch(List<T> list, T key, Comparator<T> c)
그리고 나서 <? extends T><? super T>의 의미를 덧붙이자.

- List<T> 아니고 List<? extends T>인 이유는 list에서 T형 인스턴스를
 꺼내는 것만(Get) 허용하기 위해.
- Comparator<T>아니고 Comparator<? super T>인 이유는 Ecar 클래스를 통해 설명한것.
예제 ---------------------------------------------------------------------
class StrComp implements Comparator<String> {
    @Override
    public int compare(String s1, String s2){
        return s1.compareToIgnoreCase(s2);  // 대문자, 소문자 구분 없이 비교
    }
}
public class StringComparator {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("ROBOT");
        list.add("APPLE");
        list.add("BOX");

        StrComp cmp = new StrComp(); //정렬과 탐색의 기준
        Collections.sort(list, cmp); //정렬
        int idx = Collections.binarySearch(list,"Robot",cmp);   //탐색
        System.out.println(list.get(idx));  //탐색 결과 출력
    }
}
----------------------------------------------------------------------
ROBOT

public int compareToIgnoreCase(String str)
-> 두 문자열이 같을때 0을 반환(대소문자 구분 없이함)

복사하기 copy

public static<T> void copy(List<? super T> dest,List <? extends T> src)

-> src의 내용을 dest로 복사

List<T> dest 아닌 List<? super T> dest인 이유는?
-> dest에 T형 인스턴스를 넣는 것만(Set) 허용하겠다. 꺼내면(Get) 컴파일 에러!

List<T> src 아닌 List<? extends T> src 인 이유는?
-> src로부터 T형 인스턴스 꺼내는 것만(Get) 허용하겠다. 넣으면(Set) 컴파일 에러!

예제-----------------------------------------------------------------

List<String> src = Arrays.asList("Box", "Apple", "Toy", "Robot");

        //복사본을 만든다
        List<String> dest = new ArrayList<>(src);

        //정렬하여 그 결과를 출력
        Collections.sort(dest);
        System.out.println(dest);

        // dest에 저장된 내용을 src에 저장된 내용으로 덮어씀
        Collections.copy(dest,src);

        //되돌림 확인
        System.out.println(dest); //컬렉션 인스턴스에 저장된 내용 전부 출력
---------------------------------------------------------------------
[Apple, Box, Robot, Toy]
[Box, Apple, Toy, Robot]

컬렉션 인스턴스를 생성하지 않은 상태에서 복사본을 만들려면 다음 방법을 사용하면 된다.
List<String> dest = new ArrayList<>(src);
profile
반갑습니다

0개의 댓글