ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 자바 - Arrays 클래스와 Comparator
    언어/JAVA 2023. 3. 23. 13:30

     

    -Objects,Colletions 등 배열과 관련된 static메서드 제공 

     

    배열의 복사 - copyOf(), copyOfRange():

    배열 전체 혹은 배열의 일부 복사 

     

    배열 채우기 - fill(),setAll() :

    fill()은 배열의 모든 요소를 지정된 값으로 채우고

    setAll()은 배열을 채우는데 함수형 인테페이스를 매개변수로 받는다

     

    배열의 정렬과 검색 - sort(), binarySearch(): 

    sort()는 정렬, binarySearch() 배열에 지정된 값이 저장된 index리턴 (단,배열은반드시 정렬되어 있어야함)

     

    배열의 비교와 출력 

    equals(),toString() - 다차원 배열은 deepEquals() deeptoString()사용 

     

    배열을 List로 변환 

    asList(Object...a) 배열을 리스트에 담아서 반환한다. 매개변수의 타입이 가변인수여서 배열 생성 없이 저장할 요소들 나열해도 괜찮다. 

    *이렇게 탄생한 List는 사이즈 변경 불가 삭제불가, 내용변경만 가능

    List list = Arrays.asList(...)

    List list = new ArrayList(Arrays.asList()); 이렇게 만들면 그냥 리스트처럼 쓸 수 있다.

     

    Comparator와  Comparable

     

    -Arrays의 sort()가 호출되면, 자동으로 정렬해주는게 아니라, 각 클래스에 정의된 Comparable 구현에 의해 정렬 된 것

    -Comparator과 Comparable 모두 인터페이스, 컬렉션을 정렬하는 데 필요한 메서드 정의하고 있다.

    -두 메서드 모두 객체를 비교하기 위해 존재하는 것. 정렬 기준을 제공

     

    Comparable

    pulbic int compareTo(Object o)를 구현

    매개변수로 들어온 인스턴스와 자신을 특정 기준으로 비교

    한 클래스 인스턴스에 대한 기본 정렬 기준이므로, Arrays.sort()등 정렬 메서드를 사용하고 싶으면 이를 구현해 두어야함.

     

     Comparator

    public int compare(Object o1, Object o2)를 구현

    매개변수로 들어온 두 인스턴스를 특정 기준으로 비교

    한 클래스에 대한 기본 외 다른 정렬 기준이다. 인터페이스를 구현하기 위해 새로운 클래스를 외부 혹은 내부에 만든다.

     

     

    static void sort(Object[] objArr, Comparator c){
        for(int i=0; i<objArr.length-1;i++){
            for(int j=0; j<objArr.length-1-i;j++){
                Object temp = null;
    
                if(c.compare(objArr[i],objArr[j+1])>0){ //우리는 정렬 기준만 제공
                    temp = objArr[j];
                    objArr[j] = objArr[j+1];
                    objArr[j+1] = temp;
                }
            }
        }
    }

    예를 들면 이런 것이다. sort가 버블정렬이던, 뭐던 어떠한 정렬 방법으로 구현되어 있더라도, 그건 이미 정해져있는 것이고

    우리는 어떤 기준으로 정렬의 방법을 사용할 것인지만 제공해주면 된다. 이때 Comparator가 없으면 기본정렬기준을 사용하는 것이다.

    public final class String
        implements java.io.Serializable, Comparable<String>, CharSequence 
        ///String에 compareTo
         public int compareTo(String anotherString) {
            byte v1[] = value;
            byte v2[] = anotherString.value;
            if (coder() == anotherString.coder()) {
                return isLatin1() ? StringLatin1.compareTo(v1, v2)
                                  : StringUTF16.compareTo(v1, v2);
            }
            return isLatin1() ? StringLatin1.compareToUTF16(v1, v2)
                              : StringUTF16.compareToLatin1(v1, v2);
         }
         //////////////////////////String의 다른 정렬 기준으로 대소문자 구분x//////////////////
         
          public static final Comparator<String> CASE_INSENSITIVE_ORDER
                                             = new CaseInsensitiveComparator();
        private static class CaseInsensitiveComparator //내부 클래스
                implements Comparator<String>, java.io.Serializable {
            // use serialVersionUID from JDK 1.2.2 for interoperability
            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()) {
                    return s1.isLatin1() ? StringLatin1.compareToCI(v1, v2)
                                         : StringUTF16.compareToCI(v1, v2);
                }
                return s1.isLatin1() ? StringLatin1.compareToCI_UTF16(v1, v2)
                                     : StringUTF16.compareToCI_Latin1(v1, v2);
            }

    String 내부에 정의된 compareTo()와 compare()이다. 

     

    Comparable Comparator 비교

    Comparable과 Comparator이 굳이 따로 존재하는 이유는 기존 코드의 수정없이 Comparable로 정의된 기본 정렬 기준 외에 추가 혹은 사용하고 싶은 새로운 정렬 기준을 이용해서 정렬할 수 있게 하기 위함이다. 

     

    Comparable이 구현되어있는 대부분의 클래스의 정렬기준은 오름차순이다. 그렇다면, 내림차순으로 정렬하고 싶으면 어떻게 해야할까?

    혹은 내가 정의한 임의의 클래스 Student가 있을 때, 기본 정렬은 이름의 오름차순인데, 이를 이름의 내림차순 혹은 나이의 오름/내림 차순 등으로 변경하고 싶으면 어떻게 해야할까? 

     

    -물론 기존에 기본 정렬 기준을 원하는 대로 바꿔서 다시 정렬할 수 도 있지만, 새로운 정렬기준이 생길 때마다 기존 정렬 기준을 바꾸는 것은 비효율 적이다.

    -따라서 Comprator 구현체로 새로운 정렬 기준을 만들어서  정렬시에만 적용하는 것이다.

     

    이렇게 본다면,

    -Comparable은 클래스 정의시 기본 정렬 기준을 설정하기 위해

    -Comparator는 이미 기본 정렬기준이 정의된 클래스에 새로운 정렬 기준을 추가하고 싶을 때 사용하면 된다.

     

     

    class Desending implements Comparator{
    
        @Override
        public int compare(Object o1, Object o2) {
            if(o1 instanceof Comparable && o2 instanceof Comparable){
                Comparable com1 = (Comparable) o1;
                Comparable com2 = (Comparable) o2;
                return com1.compareTo(com2) * -1; //기본 정렬 방식의 역
            }
            return -1;
        }
    }

    위와 같은 Desending을 위한 정렬기준을 Comparator 구현해서 만들었다고하면, 기존 정렬기준들을 수정할 필요 없이

    그저 sort()에 매개변수로 새로운 정렬기준을 주기만 하면 된다.

Designed by Tistory.