I have the following code:
mostRecentMessageSentDate = messageInfoList
.stream()
.findFirst().orElse(new MessageInfo())
.getSentDate();
unprocessedMessagesCount = messageInfoList
.stream()
.filter(messageInfo -> messageInfo.getProcessedDate() == null)
.count();
hasAttachment = messageInfoList
.stream()
.anyMatch(messageInfo -> messageInfo.getAttachmentCount() > 0);
As you can see, I stream the same list 3 times, because I want to find 3 different values. If I did this in a For-Each loop, I could loop just once.
Is it better, performance wise to do this a for loop then, so that I loop only once? I find the streams much more readable.
Edit: I ran some tests:
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class Main {
public static void main(String[] args) {
List<Integer> integerList = populateList();
System.out.println("Stream time: " + timeStream(integerList));
System.out.println("Loop time: " + timeLoop(integerList));
}
private static List<Integer> populateList() {
return IntStream.range(0, 10000000)
.boxed()
.collect(Collectors.toList());
}
private static long timeStream(List<Integer> integerList) {
long start = System.currentTimeMillis();
Integer first = integerList
.stream()
.findFirst().orElse(0);
long containsNumbersGreaterThan10000 = integerList
.stream()
.filter(i -> i > 10000)
.count();
boolean has10000 = integerList
.stream()
.anyMatch(i -> i == 10000);
long end = System.currentTimeMillis();
System.out.println("first: " + first);
System.out.println("containsNumbersGreaterThan10000: " + containsNumbersGreaterThan10000);
System.out.println("has10000: " + has10000);
return end - start;
}
private static long timeLoop(List<Integer> integerList) {
long start = System.currentTimeMillis();
Integer first = 0;
boolean has10000 = false;
int count = 0;
long containsNumbersGreaterThan10000 = 0L;
for (Integer i : integerList) {
if (count == 0) {
first = i;
}
if (i > 10000) {
containsNumbersGreaterThan10000++;
}
if (!has10000 && i == 10000) {
has10000 = true;
}
count++;
}
long end = System.currentTimeMillis();
System.out.println("first: " + first);
System.out.println("containsNumbersGreaterThan10000: " + containsNumbersGreaterThan10000);
System.out.println("has10000: " + has10000);
return end - start;
}
}
and as expected, the for loop is always faster than the streams
first: 0
containsNumbersGreaterThan10000: 9989999
has10000: true
Stream time: 57
first: 0
containsNumbersGreaterThan10000: 9989999
has10000: true
Loop time: 38
But never significantly.
The findFirst was probably a bad example, because it just quits if the stream is empty, but I wanted to know if it made a difference.
I was hoping to get a solution that allowed multiple calculations from one stream. IntSummaryStatistics dont do exactly what I want. I think I'll heed @florian-schaetz and stick to favouring readbility for a marginal performance increase