gpt4 book ai didi

java - 如何将具有动态值的 lambda 过滤器转换为方法引用

转载 作者:搜寻专家 更新时间:2023-10-31 19:38:24 25 4
gpt4 key购买 nike

我有一些 Java 代码可以根据某些输入过滤列表。它目前使用 lambda,例如:

public List<ComplexObject> retrieveObjectsFilteredByTags(List<String> allowedTags) {
List<ComplexObject> complexObjects = retrieveAllComplexObjects();
return complexObjects
.stream()
.filter( compObject -> allowedTags.contains(compObject.getTag()))
.collect(Collectors.toList());
}

我想做的是将过滤器逻辑移动到另一种方法,使其可重用且易于单元测试。所以我想使用方法引用来代替传递给过滤器方法的 lambda。如果过滤器逻辑相当静态(即允许的标签列表在编译时已知),则很容易做到,但我无法弄清楚如何使用过滤器中的动态数据执行此操作。

我想要的是使用方法引用然后传递第二个动态参数的某种方式,即

public List<ComplexObject> retrieveObjectsFilteredByTags(List<String> allowedTags) {
List<ComplexObject> complexObjects = retrieveAllComplexObjects();
return complexObjects
.stream()
.filter(this::filterByAllowedTags, allowedTags)
.collect(Collectors.toList());
}

那么是否有可能做我想做的事,或者我是否可能错误地处理了这种情况?

最佳答案

我建议传入一个 Predicate 作为参数。这样调用者就可以根据它想要的任何标准进行过滤,包括 allowedTags 或其他任何东西:

public List<ComplexObject> retrieveObjectsFilteredBy(Predicate<ComplexObject> pred) {
List<ComplexObject> complexObjects = retrieveAllComplexObjects();
return complexObjects.stream()
.filter(pred)
.collect(Collectors.toList());
}

这样调用:

    List<String> allowedTags = ... ;
List<ComplexObject> result =
retrieveObjectsFilteredBy(cobj -> allowedTags.contains(cobj.getTag()));

但您可以走得更远,这取决于您愿意进行多少重构。与其“检索”返回一个 List,不如让它返回一个 Stream 怎么样?而不是 retrieve-filter 方法返回一个 List,让它也返回一个 Stream 怎么样?

public Stream<ComplexObject> retrieveObjectsFilteredBy2(Predicate<ComplexObject> pred) {
Stream<ComplexObject> complexObjects = retrieveAllComplexObjects2();
return complexObjects.filter(pred);
}

调用方看起来像这样:

    List<String> allowedTags = ... ;
List<ComplexObject> result =
retrieveObjectsFilteredBy2(cobj -> allowedTags.contains(cobj.getTag()))
.collect(toList());

现在,如果您仔细观察它,您会发现 retrieve-filter 方法根本没有添加任何值,因此您不妨将它内联到调用者中:

    List<String> allowedTags = ... ;
List<ComplexObject> result =
retrieveAllComplexObjects2()
.filter(cobj -> allowedTags.contains(cobj.getTag()))
.collect(toList());

当然,根据调用者想要做什么,它可能不想将结果收集到列表中;它可能希望使用 forEach() 或其他方式处理结果。

现在你仍然可以将过滤器分解到它自己的方法中,用于测试/调试,你可以使用方法引用:

boolean cobjFilter(ComplexObject cobj) {
List<String> allowedTags = ... ;
return allowedTags.contains(cobj.getTag());
}

List<ComplexObject> result =
retrieveAllComplexObjects2()
.filter(this::cobjFilter)
.collect(toList());

如果您不希望过滤器内置允许的标签,您可以将其从谓词更改为返回谓词的高阶函数:

Predicate<ComplexObject> cobjFilter(List<String> allowedTags) {
return cobj -> allowedTags.contains(cobj.getTag());
}

List<String> allowedTags = ... ;
List<ComplexObject> result =
retrieveAllComplexObjects2()
.filter(cobjFilter(allowedTags))
.collect(toList());

这些变化中的哪一个最有意义取决于您的应用程序的外观以及您在过滤中需要什么样的动态性。

关于java - 如何将具有动态值的 lambda 过滤器转换为方法引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26634741/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com