用Java分三个步骤排序数组

时间:2017-07-19 15:00:46

标签: java arrays sorting

我有两个数组表示3D空间中的点,position[]表示XYZ,colors[]表示RGB,两者的大小均为3*total_points(例如position[0]为{{1} },X为Y,position[1]为点0的Z坐标,position[2]为红色值,color[0]为绿色,color[1]为蓝色)。

我需要做的是基本上按3个步骤对所有点进行排序:

  1. 基于X(color[2]
  2. 排序
  3. 然后根据Y(position[0]
  4. 排序
  5. 然后根据Z(position[1]
  6. 排序

    在Java中执行此操作的最有效方法是什么?

    我想到的只是做一个类似冒泡的方法和交换,并做三次。

    position[2]

2 个答案:

答案 0 :(得分:1)

面向对象编程的一个关键点是抽象。要实现它,您应该创建一个表示彩色3D点的类,例如:

public class Point {

    private final int x;

    private final int y;

    private final int z;

    private int red;

    private int green;

    private int blue;

    public Point(int x, int y, int z) {
        this.x = x;
        this.y = y;
        this.z = z;
    }

    @Override
    public String toString() {
        return "(" + x + ", " + y + ", " + z + ")";
    }

    // TODO getters for x, y and z, plus getters & setters for red, green and blue
}

注意:我添加了一个非常有用的toString()方法,可以帮助您调试代码。吸气剂和制定者留下来作为练习:)

现在,如果你有一个点数组,即Point[] points,你可以使用内置的Arrays.sort实用程序方法,它接受一个数组和一个Comparator<Point>

Point[] points = new Point[] {
    new Point(2, 3, 1), 
    new Point(2, 1, 4), 
    new Point(2, 1, 5) };

System.out.println(Arrays.toString(points)); // [(2, 3, 1), (2, 1, 4), (2, 1, 5)]

Comparator<Point> comparator = Comparator.comparingInt(Point::getX)
    .thenComparingInt(Point::getY)
    .thenComparingInt(Point::getZ);

Arrays.sort(points, comparator);

System.out.println(Arrays.toString(points)); // [(2, 1, 4), (2, 1, 5), (2, 3, 1)]

注意:我正在使用Arrays.toString实用程序方法来创建一个人类可读的数组字符串表示。

注意Comparator<Point> comparator变量的定义:我在说我想要一个比较器,它将根据int方法返回的Point.getX()值对点进行排序,然后,如果相等,则顺序将由int方法返回的Point.getY()值确定,最后,如果仍然相等,则顺序将由{返回的int值确定{1}}方法。这就是Comparator.comparingIntComparator.thenComparingInt方法的用途。

答案 1 :(得分:-2)

正如在另一个答案中提到的,抽象是一个关键点(即从你的三个整数数组中,它们松散地表示一组点到一组实际点)。这样,每次处理时总是有三个预期的坐标。

为了进一步改善答案,你可能会从更多分离中获益:

class Point {
    int x, y, z; // plus getters/setters
}

class Color {
    int r, g, b; // dito
}

class ColoredPoint {
     Point point;
     Color color;
}

现在,当您不需要它们时,您可以将点和颜色分开,但是当您这样做时(根据原始问题IIUC中的需要),您可以将它们分开。这被称为“关注分离” - 空间中的位置和颜色是不同的野兽,最好将它们分开。

关于排序,您还可以使用不同的比较器进行各种排序。

Comparator<Point> pointComparator = Comparator.comparingInt(Point::getX)
    .thenComparingInt(Point::getY)
    .thenComparingInt(Point::getZ);
// and 
Comparator<Color> colorComparator = Comparator.comparingInt(Color::getR)
    .thenComparingInt(Color::getG)
    .thenComparingInt(Color::getB);

因为您使用合成将Point和Color组合在一起,所以如果需要,您可以为ColoredPoint重用这些比较器:

Comparator<ColoredPoint> cpComparator =
    Comparator.comparing(ColoredPoint::getPoint, pointComparator)
    .thenComparing(Comparator.comparing(ColoredPoint::getColor, colorComparator));

这比我之前的回答更好,看起来像这样:

class Point implements Comparable<Point> {
    int x, y, z;

    // you can also create a separate Comparator<Point> 
    // to move the compare code outside of Point
    int compareTo(Point other) {
        // compare by position in space
        int result = this.x - other.x;
        result = (result == 0) ? result : this.y - other.y;
        result = (result == 0) ? result : this.z - other.z;
        return result;
}

Point[] arrayOfPoints = //...
Arrays.sort(arrayOfPoints);
// or
List<Point> listOfPoints = //...
Collections.sort(listOfPoints);

同样由于关注点的分离,这一点并不需要知道你希望如何排序。