哪个双值与自身比较最快?

时间:2015-07-03 10:11:51

标签: java optimization

只是将我的问题放在上下文中:我有一个类,它根据每个元素的计算得分对其构造函数中的列表进行排序。现在我想将我的代码扩展到不对列表进行排序的类的版本。最简单的(但显然不干净,我完全清楚,但时间紧迫,我现在没有时间重构我的代码)解决方案就是使用分数计算器,为每个元素分配相同的分数。

我应该选择哪个双倍价值?我个人认为+ Infinity或-Infinity因为我认为它们具有特殊的表示,这意味着它们可以快速比较。这是正确的假设吗?我不太了解java的低级实现,以确定我是否正确。

2 个答案:

答案 0 :(得分:1)

不确定这会怎样,但你考虑过自己编写吗?

关于您正在寻找具有特定性能特征的对象,这似乎有点令人担忧,这些特性不太可能始终出现在一般实现中。即使你通过实验或甚至从源代码找到一个完美的候选人,你也无法保证合同。

static class ConstDouble extends Number implements Comparable<Number> {

    private final Double d;
    private final int intValue;
    private final long longValue;
    private final float floatValue;

    public ConstDouble(Double d) {
        this.d = d;
        this.intValue = d.intValue();
        this.longValue = d.longValue();
        this.floatValue = d.floatValue();
    }

    public ConstDouble(long i) {
        this((double) i);
    }

    // Implement Number
    @Override
    public int intValue() {
        return intValue;
    }

    @Override
    public long longValue() {
        return longValue;
    }

    @Override
    public float floatValue() {
        return floatValue;
    }

    @Override
    public double doubleValue() {
        return d;
    }

    // Implement Comparable<Number> fast.
    @Override
    public int compareTo(Number o) {
        // Core requirement - comparing with myself will always be fastest.
        if (o == this) {
            return 0;
        }
        return Double.compare(d, o.doubleValue());
    }

}
// Special constant to use appropriately.
public static final ConstDouble ZERO = new ConstDouble(0);

public void test() {
    // Will use ordinary compare.
    int d1 = new ConstDouble(0).compareTo(new Double(0));
    // Will use fast compare.
    int d2 = ZERO.compareTo(new Double(0));
    // Guaranteed to return 0 in the shortest time.
    int d3 = ZERO.compareTo(ZERO);
}

显然,您需要在收藏中使用Comparable<Number>而不是Double,但这可能并不是件坏事。您可以设计一种机制来确保始终优先使用快速跟踪比较(取决于您的使用情况)。

答案 1 :(得分:1)

通常会避免0.0-0.0NaN。任何其他数字都没问题。您可以查看Double.compare实现,看看它们是否经过特殊处理:

if (d1 < d2)
    return -1;           // Neither val is NaN, thisVal is smaller
if (d1 > d2)
    return 1;            // Neither val is NaN, thisVal is larger

// Cannot use doubleToRawLongBits because of possibility of NaNs.
long thisBits    = Double.doubleToLongBits(d1);
long anotherBits = Double.doubleToLongBits(d2);

return (thisBits == anotherBits ?  0 : // Values are equal
        (thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)
         1));                          // (0.0, -0.0) or (NaN, !NaN)

然而,这取决于您的排序比较器的实现方式。如果你不使用Double.compare,那么可能没关系。

请注意,除了这些具有0.0/-0.0/NaN双重数字比较的特殊情况之外,它在CPU内部连接并且非常快,因此与您已有的其他代码相比,您不太可能获得任何显着的比较开销。