커스텀 컴퍼레이터를 사용하여 int 배열을 정렬하려면 어떻게 해야 합니까?
커스텀 컴퍼레이터를 사용하여 int 배열을 정렬해야 하는데 자바 라이브러리는 비교기와의 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);
이것은 commons-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
);
Fastutil 라이브러리에서 사용할 수 있습니다.
어레이를 복사하지 않는 경우(매우 큰 경우 등), 래퍼를 작성할 수 있습니다.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;
}
};
이제 커스텀 비교기를 사용하여 이 래퍼 목록에서 정렬할 수 있습니다.
외부 라이브러리는 필요 없습니다.
Integer[] input = Arrays.stream(arr).boxed().toArray(Integer[]::new);
Arrays.sort(input, (a, b) -> b - a); // reverse order
return Arrays.stream(input).mapToInt(Integer::intValue).toArray();
int 어레이를 integer로 변환한 후 를 사용합니다(어레이에서는 자동 박스가 동작할 가능성이 있기 때문에 첫 번째 단계만 필요합니다).
Java 8:
Arrays.stream(new int[]{10,4,5,6,1,2,3,7,9,8}).boxed().sorted((e1,e2)-> e2-e1).collect(Collectors.toList());
성능을 높이고 도중에 생성되는 개체 수를 줄이려는 경우 이클립스 컬렉션의 구현을 고려해 보십시오.
커스텀을 사용합니다.IntComparator
이 기능은 기본 요소에서 작동하므로 박스가 필요하지 않습니다.
다음은 작업을 수행하기 위한 도우미 방법입니다.
우선 Comparator 인터페이스가 필요합니다. Comparator는 기본 요소를 지원하지 않기 때문입니다.
public interface IntComparator{
public int compare(int a, int b);
}
(물론 오토박스/언박스로도 할 수 있지만, 나는 거기에 가지 않을 거야, 못생겼어.)
다음으로 이 비교기를 사용하여 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]
정렬 코드는 Arrays.sort(int[])에서 가져온 것으로 소규모 어레이용으로 최적화된 버전만 사용했습니다.실제 실장에서는 내부 메서드의 소스 코드를 참조하는 것이 좋습니다.sort1(int[], offset, length)
[ Arrays ]클래스에서 사용합니다.
나는 원시형 자체의 비교기를 최대한 사용하려고 했다.결국 나는 대조군을 속일 방법이 없다는 결론을 내렸다.이것이 나의 실장입니다.
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);
}
}
@로마: 좋은 예라고는 할 수 없지만, 당신이 물어봤기 때문에 이런 생각이 들었다.배열에서 절대값만을 기준으로 숫자를 정렬한다고 가정합니다.
Integer d1=Math.abs(o1);
Integer d2=Math.abs(o2);
return d1.compareTo(d2);
다른 예로는 100보다 큰 숫자만 정렬하는 경우가 있습니다.사실 상황에 따라 다르죠.더 이상 상황이 생각나지 않아요.Alexandru가 int 배열에 비교기를 사용하는 것을 원하기 때문에 더 많은 예를 들어줄 수 있을지도 모릅니다.
여기 복싱/언박스를 사용하지 않고도 효과적인 코드(원래는 Timsort는 아니지만 잘 작동합니다)가 있습니다.테스트에서는 Collections를 사용하는 것보다 3~4배 더 빨리 작동합니다.배열 주위에 목록 래퍼를 사용하여 정렬합니다.
// This code has been contributed by 29AjayKumar
// from: https://www.geeksforgeeks.org/sort/
static final int sortIntArrayWithComparator_RUN = 32;
// this function sorts array from left index to
// to right index which is of size atmost RUN
static void sortIntArrayWithComparator_insertionSort(int[] arr, IntComparator comparator, int left, int right) {
for (int i = left + 1; i <= right; i++)
{
int temp = arr[i];
int j = i - 1;
while (j >= left && comparator.compare(arr[j], temp) > 0)
{
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = temp;
}
}
// merge function merges the sorted runs
static void sortIntArrayWithComparator_merge(int[] arr, IntComparator comparator, int l, int m, int r) {
// original array is broken in two parts
// left and right array
int len1 = m - l + 1, len2 = r - m;
int[] left = new int[len1];
int[] right = new int[len2];
for (int x = 0; x < len1; x++)
{
left[x] = arr[l + x];
}
for (int x = 0; x < len2; x++)
{
right[x] = arr[m + 1 + x];
}
int i = 0;
int j = 0;
int k = l;
// after comparing, we merge those two array
// in larger sub array
while (i < len1 && j < len2)
{
if (comparator.compare(left[i], right[j]) <= 0)
{
arr[k] = left[i];
i++;
}
else
{
arr[k] = right[j];
j++;
}
k++;
}
// copy remaining elements of left, if any
while (i < len1)
{
arr[k] = left[i];
k++;
i++;
}
// copy remaining element of right, if any
while (j < len2)
{
arr[k] = right[j];
k++;
j++;
}
}
// iterative sort function to sort the
// array[0...n-1] (similar to merge sort)
static void sortIntArrayWithComparator(int[] arr, IntComparator comparator) { sortIntArrayWithComparator(arr, lIntArray(arr), comparator); }
static void sortIntArrayWithComparator(int[] arr, int n, IntComparator comparator) {
// Sort individual subarrays of size RUN
for (int i = 0; i < n; i += sortIntArrayWithComparator_RUN)
{
sortIntArrayWithComparator_insertionSort(arr, comparator, i, Math.min((i + 31), (n - 1)));
}
// start merging from size RUN (or 32). It will merge
// to form size 64, then 128, 256 and so on ....
for (int size = sortIntArrayWithComparator_RUN; size < n; size = 2 * size)
{
// pick starting point of left sub array. We
// are going to merge arr[left..left+size-1]
// and arr[left+size, left+2*size-1]
// After every merge, we increase left by 2*size
for (int left = 0; left < n; left += 2 * size)
{
// find ending point of left sub array
// mid+1 is starting point of right sub array
int mid = Math.min(left + size - 1, n - 1);
int right = Math.min(left + 2 * size - 1, n - 1);
// merge sub array arr[left.....mid] &
// arr[mid+1....right]
sortIntArrayWithComparator_merge(arr, comparator, left, mid, right);
}
}
}
static int lIntArray(int[] a) {
return a == null ? 0 : a.length;
}
static interface IntComparator {
int compare(int a, int b);
}
언급URL : https://stackoverflow.com/questions/3699141/how-to-sort-an-array-of-ints-using-a-custom-comparator
'source' 카테고리의 다른 글
이것은 MariaDB의 ROUND 기능의 오동작입니까? (0) | 2022.11.26 |
---|---|
지속성 중에 JPA 필드를 무시하는 가장 쉬운 방법은 무엇입니까? (0) | 2022.11.26 |
mysql datetime 비교 (0) | 2022.11.25 |
MySQL 데이터베이스 테이블의 최대 레코드 수 (0) | 2022.11.25 |
MAMP에 PHP 버전을 추가하는 방법 (0) | 2022.11.25 |