代码最优性

时间:2017-03-19 23:44:09

标签: java performance list swap indexof

每次我编码时,我都会在创建更多变量和使用方法之间陷入困境,这会使代码更清晰但不太理想?你能告诉我什么对我们的应用程序性能更好吗?

例如:

protected static <T> void exch(List<T> list, Object o1, Object o2) {
    list.set(list.indexOf(o1), list.set(list.indexOf(o2), list.get(list.indexOf(o1))));
}

我应该使用:

indexOf(o1)

两次或改变临时变量?

PS只是为了让你清楚。我为我的大学项目写了几种类型的排序方法。我们对具有~150k元素的列表进行排序。我真的希望得到最好的表现。

2 个答案:

答案 0 :(得分:4)

如果你在对象上交换,你可以做的最好的事情就是首先计算indexOf(o1)一次,因为这是一个 O(n)操作:意味着如果你有一个包含~100k元素的列表,那么与最差情况下的~50k元素相比,它将需要大约两倍的时间。你不想两次做这个昂贵的任务。所以你可以优化它:

protected static <T> void exch(List<T> list, T o1, T o2) {
    int i1 = list.indexOf(o1);
    list.set(i1, list.set(list.indexOf(o2), list.get(i1)));
}
然而,那不是全部。您无需致电list.get(i1) :您知道结果将是o1(假设您未覆盖.equals(..)方法。但如果您要排序,我假设您引用了 real 对象,而不是等效对象。所以您可以将其重写为:

protected static <T> void exch(List<T> list, T o1, T o2) {
    int i2 = list.indexOf(o2);
    list.set(list.indexOf(o1),o2);
    list.set(i2,o1);
}

此处首先获得o2 的索引至关重要:因为一旦有list.set(..,o2),就会有两个索引映射到{{ 1}} 即可。为了获得旧的,我们首先获得索引。

在方法中声明o2 对垃圾收集过程没有影响int将在调用堆栈上声明或它将使用累加器(因此根本没有内存地址)。这取决于您的处理器架构等。然而,声明int的影响在速度方面是最小的。单独进行方法调用会产生更大的影响:在调用堆栈上创建一个调用框架,必须跳转到该方法,等等。开销是&#34;大&#34;与宣布一个int相比。

然而,如果您通过 获取那里的索引交换对象,我认为您的排序算法是设计不良。如前所述,这是 O(n)操作。如果您对指数进行簿记。你可以使它成为一个 O(1)操作(这将导致大约50k的加速),这就是真正的加速所在(即使你设法充分利用{ {1}}方法,它本身将通过一个处理索引的方法来胜过。然后,您可以像下面这样实现它:

int

答案 1 :(得分:1)

如果我正在编写该方法的详细信息,我可能会这样做,如果我是为了可读性。

protected static <T> void exch(List<T> list, Object o1, Object o2) {
    int indexOfO1 = list.indexOf(o1);
    int indexOfO2 = list.indexOf(o2);
    // TODO: Handle if either indexOf was out of range.
    list.set(indexOfO2, o1);
    list.set(indexOfO1, o2);
}

我不认为像你一样在一行中这样做会在性能方面起作用。阅读有关过早优化的信息。