我有以下代码:
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);
如您所见,我将同一个列表流式传输 3 次,因为我想找到 3 个不同的值。如果我在 For-Each 循环中执行此操作,我可以只循环一次。
那么做这个 for 循环是否更好,性能更明智,这样我只循环一次?我发现流更具可读性。
编辑:我进行了一些测试:
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;
}
}
正如预期的那样,for 循环总是比流快
first: 0
containsNumbersGreaterThan10000: 9989999
has10000: true
Stream time: 57
first: 0
containsNumbersGreaterThan10000: 9989999
has10000: true
Loop time: 38
但从来没有显着。
findFirst 可能是一个不好的例子,因为如果流为空它就会退出,但我想知道它是否有所作为。
我希望得到一个允许从一个流进行多次计算的解决方案。 IntSummaryStatistics 并没有完全按照我的意愿行事。我想我会注意@florian-schaetz 并坚持支持可读性以获得边际性能提升
最佳答案
您不会遍历集合 3 次。
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);
上面只需要遍历元素,直到找到带有附件的消息。
因此,在三个流中,只有其中一个需要遍历整个集合,在最坏的情况下,您需要进行两次迭代(第二个,可能是第三个流) .
使用常规的 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;
}
}
如果您认为这是一个更好的解决方案,这真的取决于您(我还发现流更具可读性)。我看不到将三个流合并为一个流的方法,至少不是以更具可读性的方式。
关于java - 我应该流多次还是在一个流中进行所有计算?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44237839/
我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123
我的代码目前看起来像这样numbers=[1,2,3,4,5]defpop_threepop=[]3.times{pop有没有办法在一行中完成pop_three方法中的内容?我基本上想做类似numbers.slice(0,3)的事情,但要删除切片中的数组项。嗯...嗯,我想我刚刚意识到我可以试试slice! 最佳答案 是numbers.pop(3)或者numbers.shift(3)如果你想要另一边。 关于ruby-多次弹出/移动ruby数组,我们在StackOverflow上找到一
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
这里是Ruby新手。完成一些练习后碰壁了。练习:计算一系列成绩的字母等级创建一个方法get_grade来接受测试分数数组。数组中的每个分数应介于0和100之间,其中100是最大分数。计算平均分并将字母等级作为字符串返回,即“A”、“B”、“C”、“D”、“E”或“F”。我一直返回错误:avg.rb:1:syntaxerror,unexpectedtLBRACK,expecting')'defget_grade([100,90,80])^avg.rb:1:syntaxerror,unexpected')',expecting$end这是我目前所拥有的。我想坚持使用下面的方法或.join,
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/