我试图制作Predicate
以便了解我的情况
完成了一些记录,但我需要一个可以随时间更新的外部记录列表;我还需要跟踪已经处理的那些。
这就是代码的样子:
// This one is at class level and gets updated in different places
Set<String> recipients ...
private void method(Iterable<CustomType> records) {
final Set<String> doneWith = new HashSet<>();
try {
someService.doThis(records, record -> { // records is a list of CustomType
boolean notify = Stream.of(doneWith, recipients)
.noneMatch(s -> s.contains(record.getField()));
if (notify) {
doneWith.add(record.getField());
}
return notify;
});
recipients.addAll(doneWith);
} catch (Exception e) {
// TODO: Do something here
}
}
...现在我想&#34;外化&#34;进入Predicate
第二个参数someService.doThis(records, <this_one>
。有线索吗?
这是一种电话:
public void doThis(Iterable<CustomType> records, Predicate<CustomType> notify) {
records.forEach(r -> {
// Do some stuff here
if (notify.test(r)) {
// Do some more stuff here
}
});
}
注意:主要原因是希望能够重复使用它的谓词,因为我可能需要它在其他地方,但截至目前,它也用于测试案例。
答案 0 :(得分:0)
据我所知,你的功能真的只是:
record -> !recipients.contains(record.getField())
&& doneWith.add(record.getField())
答案 1 :(得分:0)
我认为您需要使用BiPredicate作为参数。
public void doThis(Iterable<CustomType> records, BiPredicate<CustomType, Iterable<CustomType> > shouldNotify) {
final Set<String> doneWith = new HashSet<>();
records.forEach(r -> {
if (shouldNotify.test(r, doneWith)) {
// Do something here
}
});
}
答案 2 :(得分:0)
如果你只想外化你的谓词,那么你只需要制作一个新的谓词:
新谓词:
@Builder
public class MyPredicate implements Predicate<CustomType> {
private Set<String> doneWith;
private Set<String> recipients;
@Override
public boolean test(CustomType record) {
boolean notify = Stream.of(doneWith, recipients)
.noneMatch(s -> s.contains(record.getField()));
if (notify) {
doneWith.add(record.getField());
}
return notify;
}
}
新来电:
private void methodName(Iterable<CustomType> records) {
someService.doThis(records, MyPredicate.builder().doneWith(doneWith).recipients(recipients).build());
recipients.addAll(doneWith);
}
继续解决你的问题我虽然这可能会有所帮助。你的谓词应该基本上只做测试。您正在谓词中执行更改操作。如果您将其移出并进行一些更改,则可能需要稍微更改代码的结构:
新谓词:
@Builder
public class MyPredicate implements Predicate<CustomType> {
private Set<String> listToFind;
@Override
public boolean test(CustomType record) {
return listToFind.parallelStream()
.noneMatch(s -> s.contains(record.getField()));
}
}
您的新来电:
private void methodName(Iterable<CustomType> records) {
someService.doThis(records,
MyPredicate.builder().listToFind(recipients).build()
.and(MyPredicate.builder().listToFind(doneWith).build())
);
recipients.addAll(doneWith);
}
最后你的新服务:
// TODO: Please consider using injection for your doneWith Set
final Set<String> doneWith = new HashSet<>();
public void doThis(Iterable<CustomType> records, Predicate<CustomType> shouldNotify) {
records.forEach(r -> {
if (shouldNotify.test(r)) {
// TODO: You continue here...
doneWith.add(r.getField());
}
});
}
因此,您现在有一个谓词,它实际上是两个谓词的 AND 条件。这样您就知道只有当所有集合都缺少customType
时,您才能在 doneWith 集中添加元素。您的服务需要共享此集合,最好的方法是使用上下文依赖注入。如果你这样做,你不需要更改你的代码那么多,你将有一个通用的谓词,你可以通用和外部使用。如果你有至少两个输入变量,那么 BiPredicate 的想法是可行的。