Java 8 流或迭代器哪个更好

Java 8 流或迭代器哪个更好,java-8,Java 8,我在玩Java*Stream API,在Lagecy系统中有以下代码: Iterator itr = configMap.entrySet().iterator(); List<String> resultList = new ArrayList<String>(); while(itr.hasNext()){ Entry e = (Entry)itr.next(); Config rc =

我在玩Java*Stream API,在Lagecy系统中有以下代码:

Iterator itr = configMap.entrySet().iterator();
        List<String> resultList = new ArrayList<String>();
        while(itr.hasNext()){
            Entry e = (Entry)itr.next();
            Config rc = (Config)e.getValue();

            if (rc != null && rc.getVisibleTo() != null && (rc.getVisibleTo().equalsIgnoreCase("0010") || rc.getVisibleTo().equalsIgnoreCase("0111") || rc.getVisibleTo().equalsIgnoreCase("0011"))){        
                resultList .add(rc.getName());
            }
        }
Iterator itr=configMap.entrySet().Iterator();
List resultList=new ArrayList();
while(itr.hasNext()){
条目e=(条目)itr.next();
Config rc=(Config)e.getValue();
如果(rc!=null&&rc.getVisibleTo()!=null&(rc.getVisibleTo().equalsIgnoreCase(“0010”)| | rc.getVisibleTo().equalsIgnoreCase(“0111”)| rc.getVisibleTo().equalsIgnoreCase(“0011”){
add(rc.getName());
}
}
我编写了与上述代码等价的流,如下所示:

List<String> resultList = configMap.entrySet()
                   .parallelStream()
                   .map(r -> r.getValue())
                   .filter(r -> r.getVisibleTo() != null)
                   .filter(r -> {return 
                              r.getVisibleTo().equalsIgnoreCase("0010")
                           || r.getVisibleTo().equalsIgnoreCase("0111")
                           || r.getVisibleTo().equalsIgnoreCase("0011");
                        })
                   .map(r -> r.getName())
                   .collect(Collectors.toList());
List resultList=configMap.entrySet()
.parallelStream()
.map(r->r.getValue())
.filter(r->r.getVisibleTo()!=null)
.filter(r->{return
r、 getVisibleTo().equalsIgnoreCase(“0010”)
||r.getVisibleTo().equalsIgnoreCase(“0111”)
||r.getVisibleTo().equalsIgnoreCase(“0011”);
})
.map(r->r.getName())
.collect(Collectors.toList());

这两种方法都能让我得到想要的结果。我的问题是,在这种情况下,哪种性能方面的写作方式更好?如果我选择其中一个而不是另一个,我是否真的获得了任何价值?地图中大约有1000个值。

首先,如果性能是您关心的问题,那么您应该根据事实来决定,所以请测量,不要猜测(即使用)

对于简单的情况,迭代或经典循环往往比流更快。另一方面,流可以更快,并且通常可以通过并行性(工作负载很容易并行化)进一步加速。在大多数情况下,这并不重要(以我的经验),因为数据集太小和/或使用它的代码没有足够的性能标准


关于可读性/可维护性,我倾向于使用流/函数方法来更好地分离关注点。但是,for-each循环也可能会改进迭代代码。因此,没有简单的是/否答案,这完全取决于上下文。

首先,如果性能是您关心的问题,您应该根据事实做出决定,所以要衡量,而不是猜测(即使用)

对于简单的情况,迭代或经典循环往往比流更快。另一方面,流可以更快,并且通常可以通过并行性(工作负载很容易并行化)进一步加速。在大多数情况下,这并不重要(以我的经验),因为数据集太小和/或使用它的代码没有足够的性能标准


关于可读性/可维护性,我倾向于使用流/函数方法来更好地分离关注点。但是,for-each循环也可能会改进迭代代码。因此,没有简单的“是/否”答案,这完全取决于上下文。

因为您将此作为并行流编写,尝试多线程并划分工作,您可能会看到管理线程的开销导致性能下降,因为您的作业有点小。这里的另一个陷阱是,由于您使用的是
CommonForkJoinPool
(默认的线程池),因此这不是一个很好的选择,因为用任务阻塞线程池会降低整个应用程序的性能(虽然这与您的工作规模不大相关,但需要记住)


也就是说,如果您使用单线程
configMap.entrySet().stream()
,那么性能差异可能会稍微慢一点,但可读性远远弥补了这一点。因此,选择是在代码速度稍快还是可读性更好之间做出决定,这完全取决于您(但我个人会选择流)。

由于您将此作为并行流编写,试图多线程并分配工作,因此您可能会看到管理线程的开销会导致性能下降,考虑到你的工作有点小。这里的另一个陷阱是,由于您使用的是
CommonForkJoinPool
(默认的线程池),因此这不是一个很好的选择,因为用任务阻塞线程池会降低整个应用程序的性能(虽然这与您的工作规模不大相关,但需要记住)


也就是说,如果您使用单线程
configMap.entrySet().stream()
,那么性能差异可能会稍微慢一点,但可读性远远弥补了这一点。因此,选择是在稍微快一点的代码还是更好的可读性之间做出决定,这完全取决于您(但我会亲自选择流)。

我只需要稍微重写
sream
示例:

List<String> resultList = configMap.entrySet()
        .parallelStream()
        .map(Map.Entry::getValue)
        .filter(Objects::nonNull) // value might be a null
        .filter(r ->
                ((Predicate<String>) "0010"::equals)
                        .or("0111"::equals) // null-save equivalent to  "0111".equals(value)
                        .or("0011"::equals)
                        .test(r.getVisibleTo())
        )
        .map(Config::getName)
        .collect(Collectors.toList());

我只想稍微重写一下
sream
示例:

List<String> resultList = configMap.entrySet()
        .parallelStream()
        .map(Map.Entry::getValue)
        .filter(Objects::nonNull) // value might be a null
        .filter(r ->
                ((Predicate<String>) "0010"::equals)
                        .or("0111"::equals) // null-save equivalent to  "0111".equals(value)
                        .or("0011"::equals)
                        .test(r.getVisibleTo())
        )
        .map(Config::getName)
        .collect(Collectors.toList());

这看起来像是基于意见的问题。有人会说a是好的。有人会说b是好的。它可能会在人与人之间产生争论,并影响此网站。这也可能会让你投反对票(不是我)。因此,请尝试编辑您的问题。为了可读性,我将从.filter(r->r.getVisibleTo()!=null)filter(r->{return r.getVisibleTo().equalsIgnoreCase(“0010”)| | r.getVisibleTo().equalsIgnoreCase(“0111”)创建一个单独的谓词| | r.getVisibleTo().equalsIgnoreCase(“0011”)})我会选择更具可读性的方法(即流方法),我非常喜欢使用
equalsIgnoreCase
。你永远不知道,也许有小写的
0
s或大写的
1
s……你最好专注于编写清晰、明显且可维护的代码,而不是关注微观性能问题。在茫茫人海中