英文:
Java Stream : How to filter conditionally?
问题
I have the following stream statement with Java Stream and I filter records based on the typeId values as types.getIds().contains(x.getType().getId())
:
return petRepository.findAll().stream()
.filter(x -> types.getIds().contains(x.getType().getId()))
.collect(Collectors.groupingBy(x -> x.getType().getName(), Collectors.counting()));
However, I want to fetch all values when types.getIds().size() == 0
and tried something as shown below:
.filter(types.getIds().size() > 0 ? x -> types.getIds().contains(x.getType().getId()) : <NO FILTERING>)
So, how can I skip filtering when types.getIds().size() == 0
?
英文:
I have the following stream statement with Java Stream and I filter records based on the typeId values as types.getIds().contains(x.getType().getId())
:
return petRepository.findAll().stream()
.filter(x -> types.getIds().contains(x.getType().getId()))
.collect(Collectors.groupingBy(x -> x.getType().getName(), Collectors.counting()));
However, I want to fetch all values when types.getIds().size() == 0
and tried something as shpon below:
.filter(types.getIds().size() > 0 ? x -> types.getIds().contains(x.getType().getId()) : <NO FILTERING>)
So, how can I skip filtering when types.getIds().size() == 0
?
答案1
得分: 5
如果您不想在每个 `x` 上检查是否为空,您可以将整个 lambda 放在一个三元表达式中:
return petRepository.findAll().stream()
.filter(types.getIds().isEmpty() ? x -> true
: x -> types.getIds().contains(x.getType().getId()))
.collect(Collectors.groupingBy(x -> x.getType().getName(), Collectors.counting()));
或者将流放入临时变量中,有条件地应用整个 `filter()`:
Stream<X> stream = petRepository.findAll().stream();
if (!types.getIds().isEmpty()) {
stream = stream.filter(x -> types.getIds().contains(x.getType().getId()));
}
return stream.collect(Collectors.groupingBy(x -> x.getType().getName(), Collectors.counting()));
英文:
If you don't want to check for empty on every x
, you can put the whole lambda in a ternary expression:
return petRepository.findAll().stream()
.filter(types.getIds().isEmpty() ? x -> true
: x -> types.getIds().contains(x.getType().getId()))
.collect(Collectors.groupingBy(x -> x.getType().getName(), Collectors.counting()));
Or pop the stream in a temporary variable and apply the entire filter()
conditionally:
Stream<X> stream = petRepository.findAll().stream();
if (!types.getIds().isEmpty()) {
stream = stream.filter(x -> types.getIds().contains(x.getType().getId()));
}
return stream.collect(Collectors.groupingBy(x -> x.getType().getName(), Collectors.counting()));
答案2
得分: 2
请记住,在filter
中的谓词必须在您希望包含结果时返回true。所以在您的情况下,筛选条件必须是这样的,如果ids不为空,那么筛选条件只有在您希望的条件下才会返回true。如果ids为空,那么筛选必须始终返回true。
您可以通过编写一个最小的测试示例(最好是使用junit或另一个测试框架模拟您的petRepository)来进行测试。
考虑以下示例:
Set<Integer> ids = Set.of(2);
List<Integer> elements = List.of(1, 2, 3);
List<Integer> list = elements.stream()
.filter(u -> ids.size() > 0 ? ids.contains(u) : true)
.toList();
System.out.println(list);
// 输出将是[2]
// 但如果ids为空,输出将是[1, 2, 3]
请注意filter
中的条件:ids.size() > 0 ? ids.contains(u) : true
如果有要检查的ids,请查看elements
的流式元素是否包含在其中。如果没有要检查的ids,无论如何都返回true(保留元素流中的所有内容以进行管道中的下一步操作)。
在这种情况下,三元表达式可以进一步简化为u -> ids.size() <= 0 || ids.contains(u)
。
英文:
You just need to remember that the predicate in the filter
has to return true whenever you want a result to be included. So in your case the filter condition must be such that, if the ids are NOT empty, filter will only return true for the condition you want. If the ids are empty, then filter must always return true.
You can play with this by writing a minimal test example (or better yet, mocking your petRepository with junit or another testing framework).
Consider:
Set<Integer> ids = Set.of(2);
List<Integer> elements = List.of(1, 2, 3);
List<Integer> list = elements.stream()
.filter(u -> ids.size() > 0 ? ids.contains(u) : true)
.toList();
System.out.println(list);
// output here will be [2]
// but if ids is empty it will be [1, 2, 3]
Look at what's inside filter
: ids.size() > 0 ? ids.contains(u) : true
If there are ids to check, see if the streamed element of elements
is contained in them. If there are no ids to check, return true regardless (keep everything in the elements stream for the next step in the pipeline).
The ternary expression in this case could be further simplified to u -> ids.size() <= 0 || ids.contains(u)
.
答案3
得分: 1
return petRepository.findAll().stream()
.filter(x -> types.getIds().isEmpty() ||
types.getIds().contains(x.getType().getId()))
.collect(Collectors.groupingBy(x -> x.getType().getName(), Collectors.counting()));
英文:
How about
return petRepository.findAll().stream()
.filter(x -> types.getIds().isEmpty() ||
types.getIds().contains(x.getType().getId()))
.collect(Collectors.groupingBy(x -> x.getType().getName(), Collectors.counting()));
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论