【问题标题】:Java 8 Optional <List> returning True Why?Java 8 可选 <List> 返回 True 为什么?
【发布时间】:2020-04-10 17:10:47
【问题描述】:

我有一个 REST 控制器

@GetMapping("/getByClientId/{clientId}")
 public ResponseEntity<Optional<List<EquityFeeds>>> getByClientId(@PathVariable("clientId") final String clientId) {

 Optional<List<EquityFeeds>> cId = Optional.ofNullable(equityFeedsService.findByClientId(clientId));

  System.out.println("Client Id: "+cId);

        if(cId.isPresent()) {
           return ResponseEntity.ok(cId);
        } else {
           cId.orElseThrow(() -> new ClientIdNotFoundException(clientId));
        }
        return ResponseEntity.ok(cId);
     }

服务类代码:

public List<EquityFeeds> findByClientId(String clientId) {

        List<EquityFeeds> cId = equityFeedsRedisRepositoryImpl.findByClientId(clientId);
        System.out.println("In EquityFeedService "+cId);
        return cId;
    }

实施。代码(REDIS):

public List<EquityFeeds> findByClientId(String clientId) {
      return (List<EquityFeeds>) listOperations.range(clientId, 0, -1);
}

问题: 1) 当使用 REST 控制器调用 getClientId 并且 clientId 不存在于 REDIS 缓存中时:

Service class Code returns: In EquityFeedService []

The REST Controller returns: Client Id: Optional[[]] 

在 REST 控制器中,代码进入 if 循环并在屏幕上不显示任何内容,因为 List 为空,即

if(cId.isPresent()) {
           return ResponseEntity.ok(cId);
 }

为什么?为什么 cId.isPresent() 返回 true 并且代码进入 if 循环。理想情况下,代码应该进入 else 循环并抛出异常,因为 List 是空的。仅在 List 的情况下会发生这种情况,因为我的其他返回类型为 POJO 的方法似乎没有此问题。

请帮助我了解此行为以及应采取哪些措施来解决此问题。

【问题讨论】:

  • Optional.ofNullable 检查是否为空。空列表不为空。
  • 那么我该如何解决这个问题。当列表为空时,我想引发用户定义的异常。我该如何解决这种情况。

标签: java spring-boot rest java-8 optional


【解决方案1】:

cId.isPresent() 返回true 因为 List&lt;EquityFeeds&gt; 不是 null ,它是空列表

if(!cId.get().isEmpty()) {
   return ResponseEntity.ok(cId);
} else {
   throw new ClientIdNotFoundException(clientId);
}

【讨论】:

  • 那么我该如何解决呢?我想在 List 为空时引发异常并返回 JSON 响应。
  • 使用 list.isEmpty() 像 cId.get().isEmpty() 一样检查
  • @Abhinash:我尝试了上面的代码。如果 else 逻辑工作正常,但在 else 块中它拒绝抛出异常。 orElseThrow() 仅适用于 isPresent() 吗?我无法抛出异常。我该如何解决这个问题?
  • @sidd 我的错,我更新了我的答案。只需使用throw new ClientIdNotFoundException(clientId);
【解决方案2】:

Optional.isPresent 返回true 的原因是存在一个实际值——一个空的ListOptional 检查它所持有的值是否为null,仅此而已。 isPresent 检查值是否存在于 Optional 中,而不是 List 本身中。

所以你必须对Optional 有点不同。此外,不要使用 Optional 这样的替代 if-else 构造。

这里有一个方法:

return cId.filter(Predicate.not(List::Empty))            // if the list is not empty
          .map(ResponseEntity::ok)                       // create a response
          .orElseThrow(() ->                             // or else throw an exception
               new ClientIdNotFoundException(clientId)); 

顺便说一句,您不想返回包裹在ResponseEntity 中的Optional。打开它并返回 List 本身。如果为空或者null已经被处理过,会先抛出异常。

return cId.filter(Predicate.not(List::Empty))            
          .map(Optional::get)                            // exctract from the Optional
          .map(ResponseEntity::ok)
          .orElseThrow(() -> new ClientIdNotFoundException(clientId)); 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-29
    • 1970-01-01
    • 1970-01-01
    • 2021-11-10
    • 2012-05-21
    • 2019-05-17
    • 2010-09-13
    相关资源
    最近更新 更多