isEmpty()如何在后台工作

时间:2019-11-15 09:25:38

标签: java algorithm

我必须优化算法并发现我们有这样的循环

while (!floorQueues.values().stream().allMatch(List::isEmpty))

似乎在每次迭代中,它都会检查此映射中的所有列表是否为空。 地图中的数据是从这样的二维数组中获取的

int currentFloorNumber = 0;
for (int[] que : queues) {
            List<Integer> list = Arrays.stream(que).boxed().collect(Collectors.toList());
            floorQueues.put(currentFloorNumber, list);
            currentFloorNumber++;
        }

我认为如果在转换数据时考虑数组中元素的数量,然后检查从列表中删除了多少次作为结束循环的条件,那将是最佳选择

while (countOfDeltedElements < totalCountOfElements)

但是当我测试代码时,它的运行速度比以前慢。所以我想知道isEmpty是如何工作的 场景比我的解决方案要快。

3 个答案:

答案 0 :(得分:2)

这可能取决于implements List类的实现。
ArrayList仅检查元素是否为0:

/**
 * Returns <tt>true</tt> if this list contains no elements.
 *
 * @return <tt>true</tt> if this list contains no elements
 */
public boolean isEmpty() {
    return size == 0;
}

答案 1 :(得分:2)

一个独特的非答案:Java性能和Java基准测试不能以这种方式工作。

您无法查看这5行源代码来了解确切的操作会在运行时发生。或更准确地说:您必须了解是非常高级的又名 complex Stream 代码可能在运行时创建大量对象,这些对象仅使用一次,然后被丢弃。为了评估真正的性能影响,您真的必须了解该代码在做什么。可能是:很多!

严肃的答案是:如果您真的需要了解发生了什么,那么您将需要:

  • 详细研究 stream 实现
  • 更糟糕的是:您将需要研究JVM内“即时”编译器的活动(例如,查看“源”代码如何转换并优化为机器代码)。
  • 最有可能的是:您将需要使用真实的事件探查器,并进行大量实验。

无论如何,您都应该开始阅读here,以确保首先测量的数字有意义。

答案 2 :(得分:1)

通常,我们有两种方法检查列表是否为空list.length() > 0!list.isEmpty()。 当我们使用list.length()时,后端发生的事情将迭代/遍历到列表的末尾,如果列表中有大量元素,则到达末尾肯定会花费很长时间。另一方面,如果我们使用'list.isEmpty()',它将仅检查列表的第一个元素是否为(O(1)),并仅在该第一个索引上返回true / false,这显然是很快的。

从性能角度出发,我们应该始终将isEmpty()用作最佳实践