用简单的 float[] 模拟 LinkedList

Mimic a LinkedList with a simple float[]

我必须在 SurfaceView 上绘制一些物体四处移动的轨迹。对象的踪迹被实现为点的 LinkedList(点是 SurfaceView 上的一对浮点坐标)。 LinkedList 是由这样的行为驱动的

    public class Trail extends LinkedList<Points> {

        private static int numbOfPoints;

        @Override
        public boolean add(Point point) {
            super.add(point);
            while( this.size() > Trail.numbOfPoints ) {
                super.remove();
            }
            return true;
        }

    }

其中 numbOfPoints 是跟踪点的最大数量。如果添加了一个新点,则将从轨迹中删除最旧的点以保持轨迹大小不变。但是当我绘制点时,为了使用 canvas.drawPoints(float[]),我会有一个 float[] 而不是一个 LinkedList of Points。所以我想出了一个从 LinkedList 到 float[] 的手动转换,它效率低下并且会造成一些麻烦...

那么,有一种方法可以避免使用 LinkedList 并直接将坐标存储到具有上述行为的 float[] 中吗?

我认为最好的实现方式是通过 ring buffer。我真的不明白你是如何使用 float[] 而不是 float[][] 在 canvas 上画东西的,但你应该能够使这个解决方案使用你喜欢的任何类型:

class Trail {
    private final int maxLength;

    private float[] points;
    private int start = 0;
    private int length = 0;

    private float[] buffer;

    public Trail(int maxLength) {
        this.maxLength = maxLength;
        this.points = new float[maxLength];
        this.buffer = new float[0];
    }

    public void add(float point) {
        points[(start + length) % points.length] = point;
        if (length < maxLength) {
            length++;
        } else {
            start = (start + 1) % points.length;
        }
    }

    public float[] getTail() {
        if (buffer.length != length) { // Reusing the array if possible.
            buffer = new float[length];
        }
        int itemsFromStartToArrayEnd = Math.min(length, points.length - start);
        System.arraycopy(points, start, buffer, 0, itemsFromStartToArrayEnd);
        if (start + length > maxLength) {
            System.arraycopy(points, 0, buffer, itemsFromStartToArrayEnd, length - itemsFromStartToArrayEnd);
        }
        return buffer;
    }
}