使用Java Stream API进行分层过滤



我有一些命令式Java条件代码,我想重构它们以使用Streams。

具体来说,我有这个映射,我想根据特定的筛选条件将其筛选到列表中。

private  Map<Integer,Thing> thingMap = new HashMap<Integer,Thing>();
// populate thingMap

下面是使用它的代码:

List<Thing> things = new ArrayList<Thing>();
for (Thing thing : thingMap.values()) {
if (thing.getCategory().equals(category)) {
if (location == null) {
things.add(thing);
} else if (thing.getLocation().equals(location)) {
things.add(thing);
}
}
}

我将其重构为以下内容。但缺少的是,如果类别过滤器通过,我希望只检查位置。此外,我怀疑还有一种更好的方法:

List<Thing> things = thingMap.entrySet()
.stream()
.filter(t -> t.getValue().getCategory().equals(category))
.filter(t -> 
location == null || 
t.getValue().getLocation().equals(location)
)
.map(Map.Entry::getValue)
.collect(Collectors.toList());

使用Streams保留分层条件检查的惯用方法是什么?

filter之后链接的操作将仅对谓词接受的元素执行。所以没有必要担心。

您也可以将条件连接到一个单独的filter步骤中,就像您可以通过使用&&组合条件将嵌套的if语句连接到单个if中一样。结果是一样的。

但请注意,循环使用条件location == null,指的是在您发布的代码片段之外声明的变量,而不是thing.getLocation() == null

除此之外,与循环相比,您还进行了其他不必要的更改。循环在映射的values()视图上迭代,而您将entrySet()用于Stream,从而需要在Map.Entry上调用getValue()四次。

循环逻辑的直接翻译要简单得多:

List<Thing> things = thingMap.values().stream()
.filter(thing -> thing.getCategory().equals(category))
.filter(thing -> location == null || thing.getLocation().equals(location))
.collect(Collectors.toList());

最新更新