Java 如何使用自定义比较器对整数数组进行排序?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3699141/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to sort an array of ints using a custom comparator?
提问by Alexandru
I need to sort an array of ints using a custom comparator, but Java's library doesn't provide a sort function for ints with comparators (comparators can be used only with objects). Is there any easy way to do this?
我需要使用自定义比较器对整数数组进行排序,但是 Java 的库没有为带有比较器的整数提供排序函数(比较器只能与对象一起使用)。有什么简单的方法可以做到这一点吗?
采纳答案by Jon Freedman
If you can't change the type of your input array the following will work:
如果您无法更改输入数组的类型,则以下内容将起作用:
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);
This uses ArrayUtils
from the commons-lang project to easily convert between int[]
and Integer[]
, creates a copy of the array, does the sort, and then copies the sorted data over the original.
这使用ArrayUtils
来自 commons-lang 项目在int[]
和之间轻松转换Integer[]
,创建数组的副本,进行排序,然后将排序后的数据复制到原始数据上。
回答by Riduidel
By transforming your int array into an Integer one and then using public static <T> void Arrays.sort(T[] a,
Comparator<? super T> c)
(the first step is only needed as I fear autoboxing may bot work on arrays).
通过将您的 int 数组转换为一个 Integer 数组然后使用public static <T> void Arrays.sort(T[] a,
Comparator<? super T> c)
(仅需要第一步,因为我担心自动装箱可能会在数组上工作)。
回答by Sean Patrick Floyd
Here is a helper method to do the job.
这是完成这项工作的辅助方法。
First of all you'll need a new Comparator interface, as Comparatordoesn't support primitives:
首先,您需要一个新的 Comparator 接口,因为Comparator不支持原语:
public interface IntComparator{
public int compare(int a, int b);
}
(You could of course do it with autoboxing / unboxing but I won't go there, that's ugly)
(你当然可以用自动装箱/拆箱来做,但我不会去那里,那很难看)
Then, here's a helper method to sort an int array using this comparator:
然后,这是使用此比较器对 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;
}
}
}
And here is some client code. A stupid comparator that sorts all numbers that consist only of the digit '9' to the front (again sorted by size) and then the rest (for whatever good that is):
这是一些客户端代码。一个愚蠢的比较器,将所有仅包含数字 '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));
Output:
输出:
[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 Arraysclass.
排序代码取自Arrays.sort(int[]),我只使用了针对小数组优化的版本。对于一个真正的实现你可能想看看内部方法的源代码sort1(int[], offset, length)
中的数组类。
回答by Emil
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.
@Roman:我不能说这是一个很好的例子,但既然你问了这个问题,我就想到了。假设在一个数组中,您只想根据它们的绝对值对数字进行排序。
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.
另一个例子可能是你只想对大于 100 的数字进行排序。这实际上取决于情况。我想不出更多的情况。也许 Alexandru 可以举出更多的例子,因为他说他想对 int 数组使用比较器.
回答by user3669782
How about using streams (Java 8)?
如何使用流(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();
Or in-place:
或就地:
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
);
回答by user1460736
If you don't want to copy the array (say it is very large), you might want to create a wrapper List<Integer>
that can be used in a sort:
如果您不想复制数组(假设它非常大),您可能需要创建一个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;
}
};
And now you can do a sort on this wrapper List using a custom comparator.
现在您可以使用自定义比较器对这个包装器列表进行排序。
回答by leventov
You can use IntArrays.quickSort(array, comparator)
from fastutil library.
您可以IntArrays.quickSort(array, comparator)
从 fastutil 库中使用。
回答by XL Zheng
You don't need external library:
您不需要外部库:
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();