Java—自定义排序数组,就像它们是元组一样
假设我有三个这样的数组:Java—自定义排序数组,就像它们是元组一样,java,arrays,sorting,tuples,Java,Arrays,Sorting,Tuples,假设我有三个这样的数组: a = [1, 2, 1, 4, 1] b = [6, 1, 2, 4, 3] c = [9, 6, 4, 7, 8] 我想对它们进行排序,就像它们是一个元组(a,b,c),因此结果应该如下所示: a | b | c ---------------------- 1 2 4 1 3 8 1 6 9 2 1 6 4
a = [1, 2, 1, 4, 1]
b = [6, 1, 2, 4, 3]
c = [9, 6, 4, 7, 8]
我想对它们进行排序,就像它们是一个元组(a,b,c),因此结果应该如下所示:
a | b | c
----------------------
1 2 4
1 3 8
1 6 9
2 1 6
4 4 7
我想用最有效的方式编写Java代码。谢谢 您应该创建一个实现
Comparable
接口的包装器对象,将数组中的值映射到此包装器类的实例,排序并使用这些值
例如:
static class X implements Comparable<X> {
final int a;
final int b;
final int c;
public X(int a, int b, int c) {
this.a = a;
this.b = b;
this.c = c;
}
public int getA() {return a;}
public int getB() {return b;}
public int getC() {return c;}
@Override
public int compareTo(X that) {
int cmp = Integer.compare(this.a, that.a);
if (cmp == 0) {
cmp = Integer.compare(this.b, that.b);
if (cmp == 0) {
cmp = Integer.compare(this.c, that.c);
}
}
return cmp;
}
}
public static void main(String[] args){
int[] a = {1, 2, 1, 4, 1};
int[] b = {6, 1, 2, 4, 3};
int[] c = {9, 6, 4, 7, 8};
IntStream.range(0, a.length)
.mapToObj(i -> new X(a[i], b[i], c[i]))
.sorted()
.forEach(x -> {
System.out.printf("%d\t%d\t%d\t\n", x.getA(), x.getB(), x.getC());
});
}
如果需要,可以将排序后的值设置回初始数组
更新
您也可以使用的改进版本,尽管它对输入整数的范围和/或数组的计数有一定的限制:
static int m = 0;
public static void main(String[] args) {
// range of integer values for 3 arrays is -2^20 ... 2^20 -1
// or 0..2^21 -1
final int[] a = { Integer.MAX_VALUE>>11, 1, 1, -4, Integer.MIN_VALUE/(1<<11) };
final int[] b = { 6, 1, 1, 4, 3 };
final int[] c = { 9, -6, -24, 7, 8 };
IntSummaryStatistics stats =
Stream.of(Arrays.stream(a), Arrays.stream(b), Arrays.stream(c))
.flatMapToInt(s -> s)
.summaryStatistics();
long min = stats.getMin();
long max = stats.getMax() - min + 1;
IntStream.range( 0, a.length )
// use long to fit multiplication results into 63 bits
.mapToLong( i -> (a[i] - min) * max * max + (b[i]-min) * max + (c[i]-min) )
.sorted()
.forEach( n -> {
// re-calculate long back to ints
a[m] = (int) (n / (max * max) % max + min);
b[m] = (int) (n / max % max + min);
c[m] = (int) (n % max + min);
System.out.printf("% 9d\t% d\t% d\t\n", a[m], b[m], c[m]);
m++;
});
}
注意上述限制可以通过使用BigDecimal
而不是long
来克服,以避免在执行乘法时溢出
导入静态java.lang.System.out;
导入java.util.array;
导入java.util.stream.IntStream;
公共类SO62961100{
静态int-i;
公共静态void main(最终字符串[]args){
final int[]a={1,2,1,4,1};
final int[]b={6,1,2,4,3};
最后的int[]c={9,6,4,7,8};
IntStream.range(0,a.length)
.map(i->a[i]*100+b[i]*10+c[i])
.已排序()
.forEach(n->{
a[i]=n/100%10;
b[i]=n/10%10;
c[i++]=n%10;
} );
out.printf(“a=%s%nb=%s%nc=%s”,
数组。toString(a),
数组。toString(b),
toString(c));
}
}
输出
您好,到目前为止您有没有尝试过的代码?排序的标准是什么?制作一个元组数组,然后对其进行排序怎么样?你知道,使用面向对象语言Java的特性,创建对象。并行阵列是一种反模式,您不应该使用它们。由Jon Skeet编写。我只是将其用于测试,因此目前不一定需要该样式。这是一个有趣的实现,但它似乎对输入数据非常敏感。如果任何输入数组包含负值,则计算将被破坏。此外,如果事先检测到最大值(而不是硬编码的10),则乘法可能导致整数溢出。
static int m = 0;
public static void main(String[] args) {
// range of integer values for 3 arrays is -2^20 ... 2^20 -1
// or 0..2^21 -1
final int[] a = { Integer.MAX_VALUE>>11, 1, 1, -4, Integer.MIN_VALUE/(1<<11) };
final int[] b = { 6, 1, 1, 4, 3 };
final int[] c = { 9, -6, -24, 7, 8 };
IntSummaryStatistics stats =
Stream.of(Arrays.stream(a), Arrays.stream(b), Arrays.stream(c))
.flatMapToInt(s -> s)
.summaryStatistics();
long min = stats.getMin();
long max = stats.getMax() - min + 1;
IntStream.range( 0, a.length )
// use long to fit multiplication results into 63 bits
.mapToLong( i -> (a[i] - min) * max * max + (b[i]-min) * max + (c[i]-min) )
.sorted()
.forEach( n -> {
// re-calculate long back to ints
a[m] = (int) (n / (max * max) % max + min);
b[m] = (int) (n / max % max + min);
c[m] = (int) (n % max + min);
System.out.printf("% 9d\t% d\t% d\t\n", a[m], b[m], c[m]);
m++;
});
}
-1048576 3 8
-4 4 7
1 1 -24
1 1 -6
1048575 6 9
a=[1, 1, 1, 2, 4]
b=[2, 3, 6, 1, 4]
c=[4, 8, 9, 6, 7]