programing tip

사용자 지정 비교기를 사용하여 int 배열을 정렬하는 방법은 무엇입니까?

itbloger 2020. 12. 9. 07:54
반응형

사용자 지정 비교기를 사용하여 int 배열을 정렬하는 방법은 무엇입니까?


사용자 정의 비교기를 사용하여 int 배열을 정렬해야하지만 Java의 라이브러리는 비교기가있는 int에 대한 정렬 기능을 제공하지 않습니다 (비교자는 객체에만 사용할 수 있음). 이 작업을 수행하는 쉬운 방법이 있습니까?


입력 배열의 유형을 변경할 수없는 경우 다음이 작동합니다.

final int[] data = new int[] { 5, 4, 2, 1, 3 };
final Integer[] sorted = ArrayUtils.toObject(data);
Arrays.sort(sorted, new Comparator<Integer>() {
    public int compare(Integer o1, Integer o2) {
        // Intentional: Reverse order for this demo
        return o2.compareTo(o1);
    }
});
System.arraycopy(ArrayUtils.toPrimitive(sorted), 0, data, 0, sorted.length);

이것은 ArrayUtilscommons-lang 프로젝트에서 사용 하여 int[]사이를 쉽게 변환 하고 Integer[], 배열의 복사본을 만들고, 정렬 한 다음, 정렬 된 데이터를 원본 위에 복사합니다.


스트림 (Java 8)을 사용하는 것은 어떻습니까?

int[] ia = {99, 11, 7, 21, 4, 2};
ia = Arrays.stream(ia).
    boxed().
    sorted((a, b) -> b.compareTo(a)). // sort descending
    mapToInt(i -> i).
    toArray();

또는 현재 위치 :

int[] ia = {99, 11, 7, 21, 4, 2};
System.arraycopy(
        Arrays.stream(ia).
            boxed().
            sorted((a, b) -> b.compareTo(a)). // sort descending
            mapToInt(i -> i).
            toArray(),
        0,
        ia,
        0,
        ia.length
    );

배열을 복사하지 않으려면 (매우 큰 경우) List<Integer>정렬에 사용할 수 있는 래퍼를 만들 수 있습니다.

final int[] elements = {1, 2, 3, 4};
List<Integer> wrapper = new AbstractList<Integer>() {

        @Override
        public Integer get(int index) {
            return elements[index];
        }

        @Override
        public int size() {
            return elements.length;
        }

        @Override
        public Integer set(int index, Integer element) {
            int v = elements[index];
            elements[index] = element;
            return v;
        }

    };

이제 사용자 지정 비교기를 사용하여이 래퍼 목록을 정렬 할 수 있습니다.


int 배열을 Integer로 변환 한 다음 사용하십시오 public static <T> void Arrays.sort(T[] a, Comparator<? super T> c)(첫 번째 단계는 autoboxing이 배열에서 작동 할 수 있다는 것을 두려워하기 때문에 필요합니다).


IntArrays.quickSort(array, comparator)fastutil 라이브러리에서 사용할 수 있습니다 .


다음은 작업을 수행하는 도우미 방법입니다.

우선 Comparator 는 기본 요소를 지원하지 않으므로 새로운 Comparator 인터페이스가 필요합니다 .

public interface IntComparator{
    public int compare(int a, int b);
}

(물론 autoboxing / unboxing으로 할 수 있지만 거기에 가지 않을 것입니다.

그런 다음이 비교기를 사용하여 int 배열을 정렬하는 도우미 메서드는 다음과 같습니다.

public static void sort(final int[] data, final IntComparator comparator){
    for(int i = 0; i < data.length + 0; i++){
        for(int j = i; j > 0
            && comparator.compare(data[j - 1], data[j]) > 0; j--){
            final int b = j - 1;
            final int t = data[j];
            data[j] = data[b];
            data[b] = t;
        }
    }
}

다음은 클라이언트 코드입니다. 숫자 '9'로만 구성된 모든 숫자를 앞쪽으로 (다시 크기별로 정렬 됨) 정렬 한 다음 나머지 (좋은 것이 무엇이든간에)를 정렬하는 어리석은 비교기 :

final int[] data =
    { 4343, 544, 433, 99, 44934343, 9999, 32, 999, 9, 292, 65 };
sort(data, new IntComparator(){

    @Override
    public int compare(final int a, final int b){
        final boolean onlyNinesA = this.onlyNines(a);
        final boolean onlyNinesB = this.onlyNines(b);
        if(onlyNinesA && !onlyNinesB){
            return -1;
        }
        if(onlyNinesB && !onlyNinesA){
            return 1;
        }

        return Integer.valueOf(a).compareTo(Integer.valueOf(b));
    }

    private boolean onlyNines(final int candidate){
        final String str = String.valueOf(candidate);
        boolean nines = true;
        for(int i = 0; i < str.length(); i++){
            if(!(str.charAt(i) == '9')){
                nines = false;
                break;
            }
        }
        return nines;
    }
});

System.out.println(Arrays.toString(data));

산출:

[9, 99, 999, 9999, 32, 65, 292, 433, 544, 4343, 44934343]

The sort code was taken from Arrays.sort(int[]), and I only used the version that is optimized for tiny arrays. For a real implementation you'd probably want to look at the source code of the internal method sort1(int[], offset, length) in the Arrays class.


I tried maximum to use the comparator with primitive type itself. At-last i concluded that there is no way to cheat the comparator.This is my implementation.

public class ArrSortComptr {
    public static void main(String[] args) {

         int[] array = { 3, 2, 1, 5, 8, 6 };
         int[] sortedArr=SortPrimitiveInt(new intComp(),array);
         System.out.println("InPut "+ Arrays.toString(array));
         System.out.println("OutPut "+ Arrays.toString(sortedArr));

    }
 static int[] SortPrimitiveInt(Comparator<Integer> com,int ... arr)
 {
    Integer[] objInt=intToObject(arr);
    Arrays.sort(objInt,com);
    return intObjToPrimitive(objInt);

 }
 static Integer[] intToObject(int ... arr)
 {
    Integer[] a=new Integer[arr.length];
    int cnt=0;
    for(int val:arr)
      a[cnt++]=new Integer(val);
    return a;
 }
 static int[] intObjToPrimitive(Integer ... arr)
 {
     int[] a=new int[arr.length];
     int cnt=0;
     for(Integer val:arr)
         if(val!=null)
             a[cnt++]=val.intValue();
     return a;

 }

}
class intComp implements Comparator<Integer>
{

    @Override //your comparator implementation.
    public int compare(Integer o1, Integer o2) {
        // TODO Auto-generated method stub
        return o1.compareTo(o2);
    }

}

@Roman: I can't say that this is a good example but since you asked this is what came to my mind. Suppose in an array you want to sort number's just based on their absolute value.

Integer d1=Math.abs(o1);
Integer d2=Math.abs(o2);
return d1.compareTo(d2);

Another example can be like you want to sort only numbers greater than 100.It actually depends on the situation.I can't think of any more situations.Maybe Alexandru can give more examples since he say's he want's to use a comparator for int array.

참고URL : https://stackoverflow.com/questions/3699141/how-to-sort-an-array-of-ints-using-a-custom-comparator

반응형