Java 8 个流 - 将固定数量的谓词过滤器应用于单个流
Java 8 Streams - Apply fixed amount of predicate filters to single Stream
有没有办法将固定数量的 Predicates
应用于打开的 Stream
?我真的无法让我的任何尝试工作。要么尝试以流关闭错误结束,要么没有应用所有过滤器。
示例:
// list of all JLabels of any container
private final List<JLabel> listOfLabels = new ArrayList<>();
// set of user-defined filters
private final Set<Predicate<JLabel>> filters = new HashSet<>();
// let's add some filters
filters.add(label -> label.getBackground() == Color.RED);
filters.add(label -> label.getWidth() > 500);
如何将所有过滤器应用于 listOfFiles
的流?假设我们要隐藏 JLabels
不匹配这些过滤器。我正在寻找类似下面的非工作代码片段的东西。
public void applyFilters() {
listOfLabels.forEach(label -> label.setVisible(false)); // hide all labels
Stream<JLabel> stream = listOfLabels.stream();
filters.forEach(stream::filter);
stream.forEach(label -> label.setVisible(true));
// stream closed error
}
执行方法 applyFilters()
后,容器应该只有与 filters
集定义的所有谓词相匹配的可见标签。 (本例中的红色背景和宽度大于 500)。
当您使用 Stream 时,您必须始终使用 link 到 Stream 对象,该对象是 return 通过应用先前的操作。
从 API:
可以看出
Stream<T> filter(Predicate<? super T> predicate);
Stream 对象是 returned 并且 javadoc 说:
Returns a stream consisting of the elements of this stream that match
* the given predicate.
考虑到这一点,对于您的情况,我们可以应用如下内容:
转换:
filters.forEach(stream::filter);
收件人:
for (Predicate<JLabel> filter : filters) {
stream = stream.filter(filter);
}
这应该可行,因为现在您将 link 更新为 Stream 对象并遵循文档。
试试这个。
public void applyFilters() {
listOfLabels.forEach(label -> label.setVisible(false));
listOfLabels.stream()
.filter(label -> filters.stream()
.allMatch(predicate -> predicate.test(label)))
.forEach(label -> label.setVisible(true));
}
您可以先通过 Predicate::and
运算符将所有过滤器缩减为一个过滤器:
Predicate<JLabel> allFilters = filters.stream()
.reduce(Predicate::and)
.orElse(t -> true);
然后,使用这个简化的过滤器过滤:
listOfLabels.forEach(label -> label.setVisible(false));
listOfLabels.stream()
.filter(allFilters)
.forEach(label -> label.setVisible(true));
对于这最后一步,您可能还想采用稍微不同的方法:
listOfLabels.forEach(label -> label.setVisible(allFilters.test(label)));
这样做的好处是只需要遍历一次标签。
有没有办法将固定数量的 Predicates
应用于打开的 Stream
?我真的无法让我的任何尝试工作。要么尝试以流关闭错误结束,要么没有应用所有过滤器。
示例:
// list of all JLabels of any container
private final List<JLabel> listOfLabels = new ArrayList<>();
// set of user-defined filters
private final Set<Predicate<JLabel>> filters = new HashSet<>();
// let's add some filters
filters.add(label -> label.getBackground() == Color.RED);
filters.add(label -> label.getWidth() > 500);
如何将所有过滤器应用于 listOfFiles
的流?假设我们要隐藏 JLabels
不匹配这些过滤器。我正在寻找类似下面的非工作代码片段的东西。
public void applyFilters() {
listOfLabels.forEach(label -> label.setVisible(false)); // hide all labels
Stream<JLabel> stream = listOfLabels.stream();
filters.forEach(stream::filter);
stream.forEach(label -> label.setVisible(true));
// stream closed error
}
执行方法 applyFilters()
后,容器应该只有与 filters
集定义的所有谓词相匹配的可见标签。 (本例中的红色背景和宽度大于 500)。
当您使用 Stream 时,您必须始终使用 link 到 Stream 对象,该对象是 return 通过应用先前的操作。 从 API:
可以看出Stream<T> filter(Predicate<? super T> predicate);
Stream 对象是 returned 并且 javadoc 说:
Returns a stream consisting of the elements of this stream that match * the given predicate.
考虑到这一点,对于您的情况,我们可以应用如下内容:
转换:
filters.forEach(stream::filter);
收件人:
for (Predicate<JLabel> filter : filters) {
stream = stream.filter(filter);
}
这应该可行,因为现在您将 link 更新为 Stream 对象并遵循文档。
试试这个。
public void applyFilters() {
listOfLabels.forEach(label -> label.setVisible(false));
listOfLabels.stream()
.filter(label -> filters.stream()
.allMatch(predicate -> predicate.test(label)))
.forEach(label -> label.setVisible(true));
}
您可以先通过 Predicate::and
运算符将所有过滤器缩减为一个过滤器:
Predicate<JLabel> allFilters = filters.stream()
.reduce(Predicate::and)
.orElse(t -> true);
然后,使用这个简化的过滤器过滤:
listOfLabels.forEach(label -> label.setVisible(false));
listOfLabels.stream()
.filter(allFilters)
.forEach(label -> label.setVisible(true));
对于这最后一步,您可能还想采用稍微不同的方法:
listOfLabels.forEach(label -> label.setVisible(allFilters.test(label)));
这样做的好处是只需要遍历一次标签。