【问题标题】:How to increase the performance with Java ArrayList如何使用 Java ArrayList 提高性能
【发布时间】:2018-06-27 12:45:47
【问题描述】:

我正在使用一个巨大的 ArrayList 和下面的代码

public final List<MyClass> list = new ArrayList<>();

public void update(MyClass myClass) {
int i;
for (i=0; i < list.size(); i++) {
        if (myClass.foo(list.get(i))) {
            list.set(i, myClass);
            break;
        }    
    }    
    if (i == list.size()) {    
        list.add(myClass);    
    }    
}

列表非常大。在这种情况下,我还可以做些什么来提高性能?也许使用一些 Java 8 功能,替换 ArrayList 或类似的东西。

与此列表相关的另一个运行时间过长的代码是下面的代码:

public List<MyClass> something(Integer amount) {
list.sort((m1, m2) -> Double.compare(m2.getBar(), m1.getBar()));
return list.stream()
        .limit(amount)
        .collect(Collectors.toList());
}

欢迎大家帮忙,谢谢

【问题讨论】:

  • Arrays 比 ArrayLists 快得疯狂,所以如果你可以将你的结构从 ArrayList 更改为 Array,你会大大提高性能。但是,从 ArrayList 更改为 Array 可能很困难。
  • foo 函数有什么作用?您的列表中有多少个对象?
  • @ValentinMichalak foo 函数只需将当前对象与参数 objet 与等号进行比较。我的列表中有上千个对象
  • 我认为 ArrayList 不是正确的数据模型。为什么你不使用 HashMap ?
  • 您只是在比较 equals - 这就是 Maps 的用途!当amount 远小于list.size() 时,第二个问题可能会变得更快,但也许更简单——只需告诉我们Bar 与equals 的关系即可。

标签: java performance arraylist collections


【解决方案1】:

看来ArrayList的选择不太好。

在第一种情况下,您尝试通过列表中的属性查找对象。要在列表中查找对象,您必须签入列表中的每个元素。列表越大,它就会越长。 (ArrayList 的最坏情况复杂度为 O(N))

如果您使用HashMap 而不是List,则可以将您的属性用作地图的键。像这样,您可以直接选择需要更新的对象,而无需检查列表中的每个元素。执行时间将不再取决于条目数。 (HashMap 的最坏情况复杂度为 O(1))

如果您使用HashMap 而不是ArrayList,您的更新代码将如下所示:

public void update(MyClass myClass) {
    map.put(myClass.getKey(), myClass);
}

(其中getKey() 是您尝试在 foo 方法中等于的属性)。

但这仅适用于第一种情况。根据我们掌握的信息,这似乎是最好的解决方案。

【讨论】:

  • 非常感谢 Valentim,我会尝试更改为 HashMap 并将结果放在这里!
  • 我只是更改了代码 public void update(MyClass myClass) { map.put(myClass.getKey(), myClass); }
【解决方案2】:

在这种情况下,我还可以做些什么来提高性能?

问题是您的算法必须将myClass.foo 应用于列表的每个元素,直到找到第一个 匹配项。如果您连续执行此操作,那么最坏情况的复杂性是O(N),其中N 是列表大小。 (而且列表很大。)

现在,您可以并行进行搜索。但是,如果可以有多个匹配项,那么匹配列表中的第一个将是棘手的。你仍然会得到O(N/C),其中C 是可用的核心数。

O(N) 更好的唯一方法是使用不同的数据结构。但是在不知道MyClass::foo 方法的作用的情况下,很难说该数据结构应该是什么。


您的第二个问题似乎是试图解决“N 中的前 K”问题。这可以在O(N log K) 中实现,并且可能更好;见Optimal algorithm for returning top k values from an array of length N

【讨论】:

  • 直接在答案中添加复杂性的好主意。我更新了我的答案。
  • 这就是 myClass.foo 所做的事情 public boolean foo(Myclass other) { return source.equals(other.source); }
  • 在这种情况下,您应该使用HashSet。您正在执行的操作的性能将是 O(1),您可以将其实现为 set.add(myClass)。当然,你的 equals 和 hashcode 方法必须遵守 equals/hashcode 协定。阅读 javadocs。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-30
  • 2015-02-08
  • 2012-04-29
  • 2016-01-10
相关资源
最近更新 更多