0

I have to optimize and algorithm and i noticed that we have a loop like this

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

It seems like on each iteration it checks if all of the lists in this map are empty. The data in the map is taken from a two dimensional array like this

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

I thought that it will be more optimal if i take the count of elements in the arrays when transforming the data and then check how many times i deleted from the lists as a condition to end the loop

while (countOfDeltedElements < totalCountOfElements)

but when i tested the code it runs slower that before. So i wonder how isEmpty works behind the scenes to be faster than my solution.

  • 3
    You *seem* to be going after micro optimizations. Be sure to check https://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java . On this line, my first thought would be to change,`not(all(isEmpty))` to `any(not(isEmpty))`, which can be faster, by short circuiting the iteration. But then again, have you really looked at where your time is spent ? This looks like a **tiny** thing to optimize. I'd much rather think about why you collect an `int[]` to an `ArrayList`, which may be an order of magnitude more costly, seeing the little code you've shown. – GPI Nov 15 '19 at 09:35
  • You are right. It seems like somebody collect and int[] to ArrayList because is easier to manage resizing. – Ivaylo Hristov Nov 15 '19 at 09:41
  • I would recommend using a java decompiler to look into such functions. If you are using an IDE like Eclipse or IntelliJ, you can install it easily from their plugin marketplace. – www.hybriscx.com Nov 15 '19 at 10:05

3 Answers3

2

This may depend on the implementation of the class that implements List.
An ArrayList simply checks if there are 0 elements:

/**
 * 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;
}
deHaar
  • 17,687
  • 10
  • 38
  • 51
2

A distinct non-answer: Java performance, and Java benchmarking doesn't work this way.

You can't look at these 5 lines of source code to understand what exactly will happen at runtime. Or to be precise: you have to understand that streams are a very advanced, aka complex thing. Stream code might create plenty of objects at runtime, that are only used once, and then thrown away. In order to assess the true performance impacts, you really have to understand what that code is doing. And that could be: a lot!

The serious answer is: if you really need to understand what is going on, then you will need to:

  • study the stream implementation in great detail
  • and worse: you will need to look into the activities of the Just in Time compiler within the JVM (to see for example how that "source" code gets translated and optimised to machine code).
  • and most likely: you will need to apply a real profiler, and to plenty of experiments.

In any case, you should start reading here to ensure that the numbers you are measuring make sense in the first place.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
1

Normally we have two ways to check if the list is empty or not either list.length() > 0 or !list.isEmpty() . when we use list.length() what happen at backend it will iterate/go through till the end of list and if the list have big numbers of elements and it will surely going to take long to reach the end .On the other hand, if we use 'list.isEmpty()' then it will check only first element of the list if its their or not (O(1)) and return true/false just on this first index which is obviously fast.

From performance prespective , we should alwayz use isEmpty() as best practice

Noshaf
  • 207
  • 7
  • 21