【问题标题】:How to check if Collection is not empty using java Stream如何使用java Stream检查Collection是否为空
【发布时间】:2015-06-03 22:08:11
【问题描述】:

我是 Java 8 的新手。我无法理解以下代码中有什么问题。这个想法是发送Collection<User>,如果它不为空。但是如果集合为空则发送HttpStatus.NOT_FOUND实体响应。

@RequestMapping(value = "/find/pks", 
                method = RequestMethod.GET, 
                produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Collection<User>> getUsers(@RequestBody final Collection<String> pks)
{
    return StreamSupport.stream(userRepository.findAll(pks).spliterator(), false)
         .map(list -> new ResponseEntity<>(list , HttpStatus.OK))
         .orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}

Eclipse 在以下点向我显示错误.orElse

Stream&lt;ResponseEntity&lt;User&gt;&gt; 类型的方法 orElse(new ResponseEntity&lt;&gt;(HttpStatus.NOT_FOUND)) 未定义

我的基本接口方法如下所示

Iterable<T> findAll(Iterable<PK> pks);

【问题讨论】:

  • Stream.map() 返回一个 Stream,而 Stream 没有 orElse() 方法。你通过返回一个 Iterable 使你自己的生活变得复杂。为什么不返回 List 或 Set,甚至是 Collection,并使用 isEmpty()?顺便说一句,您映射的不是列表,而是用户。如果你真的想继续使用Iterable,使用iterable.iterator().hasNext() 看看它是否为空。
  • 该接口由 Spring 包之一提供。 ))))
  • 然后使用 iterable.iterator().hasNext() 看是否为空。但话虽如此,在这种情况下我不会返回 404。只需返回一个 200 和一个空列表。 404 用于您尝试获取的未知资源。您在此处搜索资源,但未找到任何内容是有效结果。

标签: java lambda java-8 java-stream


【解决方案1】:

你把两件事混为一谈了。第一个任务是将Iterable 转换为Collection,您确实可以使用Stream API 解决这个问题:

Collection<User> list=
    StreamSupport.stream(userRepository.findAll(pks).spliterator(), false)
   .collect(Collectors.toList());

请注意,此流是Users 的,而不是列表流。因此,您不能使用此流将 list 映射到其他内容。 map 操作会将流的每个元素映射到一个新元素。

然后你可以使用这个列表来创建ResponseEntity

return list.isEmpty()? new ResponseEntity<>(HttpStatus.NOT_FOUND):
                       new ResponseEntity<>(list, HttpStatus.OK);

您可以通过创建Collector 执行这些步骤来组合这些步骤,尽管这没有任何优势,这只是风格问题:

ResponseEntity<User> responseEntity=
    StreamSupport.stream(userRepository.findAll(pks).spliterator(), false)
   .collect(Collectors.collectingAndThen(Collectors.toList(),
      list -> list.isEmpty()? new ResponseEntity<>(HttpStatus.NOT_FOUND):
                              new ResponseEntity<>(list, HttpStatus.OK) ));

【讨论】:

  • 非常感谢 Holger 的回答。我修改了您的代码并包含了将每个用户转换为 UserDTO 的 map 函数。 'StreamSupport.stream(userRepository.findAll(pks).spliterator(), false).map(UserDTO::new).collect( Collectors.collectingAndThen(Collectors.toList(), list -> list.isEmpty() ? new ResponseEntity (HttpStatus.NOT_FOUND) : new ResponseEntity(list, HttpStatus.OK)));'
  • Collectors.collectingAndThen() 是一个不错的静态方法。
【解决方案2】:

将所有内容都塞进一行没有必要,而且通常是错误的。在这种情况下,你不能 - 没有这样的 API 适合你的意图。

保持简单:

Collection<User> list = <your stream code that gets a list>;
if (list.isEmpty())
    return new ResponseEntity<>(HttpStatus.NOT_FOUND);
return new ResponseEntity<>(list, HttpStatus.OK);

但如果你绝对必须

return <your code>.map(list -> new ResponseEntity<>(list, list.isEmpty() ? HttpStatus.NOT_FOUND : HttpStatus.OK));

【讨论】:

  • 他在问一个一般问题的简化版本。如果对生成流的集合应用了过滤,那么它是否为空就不是很明显了。
【解决方案3】:

这取决于你对流的终端操作,记住一个流只能被消费一次。

  • 是分组依据/统计操作吗?然后你会得到一个 0 计数或一个空的组图。
  • 如果它收集到一个列表中,那么它是一个空列表。
  • 如果它是返回Optional 的方法之一(例如findAny),那么您可以使用可选的空值检查方法。

【讨论】:

  • 但他所寻找的不是流式传输和传递的概念,而是当某些东西真正通过时做一些附带逻辑?所以不要打破流式传输或消费一次的概念......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-12
  • 2020-01-16
  • 2021-03-23
  • 2015-05-02
  • 1970-01-01
相关资源
最近更新 更多