我有以下代码:
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);
Run Code Online (Sandbox Code Playgroud)
如您所见,我将相同的列表流式传输3次,因为我想找到3个不同的值.如果我在For-Each循环中执行此操作,我只能循环一次.
这样做是否更好,性能明智的循环呢,所以我只循环一次?我发现这些流更具可读性.
编辑:我运行了一些测试:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,for循环总是比流更快
first: 0
containsNumbersGreaterThan10000: 9989999
has10000: true
Stream time: 57
first: 0
containsNumbersGreaterThan10000: 9989999
has10000: true
Loop time: 38
Run Code Online (Sandbox Code Playgroud)
但从来没有显着.
findFirst可能是一个不好的例子,因为它只是在流是空的时候退出,但我想知道它是否有所作为.
我希望得到一个允许从一个流中进行多次计算的解决方案.IntSummaryStatistics并不完全符合我的要求.我想我会留意@ florian-schaetz并坚持赞成可读性以获得边际性能提升
您不会遍历集合三次.
mostRecentMessageSentDate = messageInfoList
.stream()
.findFirst().orElse(new MessageInfo())
.getSentDate();
Run Code Online (Sandbox Code Playgroud)
以上检查集合中是否有任何元素,并根据此值返回值.它不需要经历整个集合.
unprocessedMessagesCount = messageInfoList
.stream()
.filter(messageInfo -> messageInfo.getProcessedDate() == null)
.count();
Run Code Online (Sandbox Code Playgroud)
这个需要过滤掉没有进程日期的所有元素并对它们进行计数,因此这个元素遍历整个集合.
hasAttachment = messageInfoList
.stream()
.anyMatch(messageInfo -> messageInfo.getAttachmentCount() > 0);
Run Code Online (Sandbox Code Playgroud)
以上只需要遍历元素,直到找到带附件的消息.
因此,在三个流中,只需要其中一个流经过整个集合,在最坏的情况下,您需要进行两次迭代(第二次,可能是第三次流).
使用常规For-Each循环可能会更高效,但你真的需要它吗?如果你的集合只包含一些对象,我就不会打扰它了.
但是,使用传统的For-Each循环,您可以组合最后两个流:
int unprocessedMessagesCount = 0;
boolean hasAttachment = false;
for (MessageInfo messageInfo: messageInfoList) {
if (messageInfo.getProcessedDate() == null) {
unprocessedMessagesCount++;
}
if (hasAttachment == false && messageInfo.getAttachmentCount() > 0) {
hasAttachment = true;
}
}
Run Code Online (Sandbox Code Playgroud)
如果您认为这是一个更好的解决方案(我也发现流更具可读性),这取决于您.我没有看到将三个流合并为一个的方法,至少不是以更易读的方式.
| 归档时间: |
|
| 查看次数: |
685 次 |
| 最近记录: |