【问题标题】:Code optimality代码优化
【发布时间】:2017-03-19 23:44:09
【问题描述】:

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

例如:

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 个元素的列表进行排序。我真的很想得到最好的表现。

【问题讨论】:

  • 如果你排序,你不应该在 objects 上交换,而是在 indices 上交换。
  • 您是否考虑过使用临时变量可能会使代码更清晰?因为 1 行的信息会更少。
  • 好吧,也许你是对的。但是内存呢?每次比较它们时创建新变量真的值得吗?我听说垃圾收集器很慢:/
  • @classOlek:自己衡量性能,看看每个人的表现如何(制作局部变量与不制作)。我不认为引入本地 int 变量会影响垃圾回收,因为这是针对对象的。
  • 不离开方法的对象通常可以被 JIT 编译器虚拟化,所以它们不会被 GC'd。但在这种情况下,类型将是int,它不由垃圾收集器管理。

标签: java performance list swap indexof


【解决方案1】:

如果你交换对象,你能做的最好的就是首先计算一次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 对象,而不是 equivalent 对象。因此您可以将其重写为:

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),就有两个索引映射到o2 >。为了得到旧的,我们首先要获取索引。

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

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

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

【讨论】:

    【解决方案2】:

    如果我要编写该方法的详细信息,如果我想提高可读性,我可能会这样做。

    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);
    }
    

    我不认为像你那样在一行中做这件事对性能有影响。阅读有关过早优化的信息。

    【讨论】:

      猜你喜欢
      • 2022-11-23
      • 2011-12-21
      • 2011-12-09
      • 2012-11-13
      • 2011-11-30
      相关资源
      最近更新 更多