将数组迭代转换为lambda表达式

16

我有下面的代码,它遍历Cookies以重置名称与CookieSession.NAME匹配的cookie

  Cookie[] cookies = httpServletRequest.getCookies();
        LOGGER.info("Clearing cookies on welcome page");
        if (cookies != null)
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals(CookieSession.NAME)) {                      
                cookie.setValue(null);
                cookie.setMaxAge(0);
                cookie.setPath("/");
                httpServletResponse.addCookie(cookie);
              }
            }

有人能否使用Java 8 Lambda表达式来简化它?


3
可以的。但你需要在if条件语句中添加 {} ,来解决缺失问题。 - njzk2
7
不完全是,不会被简化;它基本上是一样的,但会更加复杂一些。 - Louis Wasserman
Lambda表达式并不能让这个过程更简单。它会使得程序变得更慢,占用更多的内存,但并不会让它更简单。 - Boann
5个回答

9

不确定是否需要精简,但是它可以实现,是的:

Arrays.stream(cookies)
      .filter(c -> c.getName().equals(CookieSession.NAME))
      .forEach(cookie -> {
          cookie.setValue(null);
          cookie.setMaxAge(0);
          cookie.setPath("/");
          httpServletResponse.addCookie(cookie);
      });

2
从技术上讲,它不会等同于OP的代码,因为OP的代码缺少括号,只有第一个setter会依赖于if...但无论如何,您的代码确实做到了他所期望的。 - Jean-François Savard
1
值得指出的是,仍然需要进行空值检查。如果没有cookie,则httpServletRequest.getCookies()返回null,而Arrays.stream不支持空值。此外,由于HttpServletResponse未指定为线程安全,因此最好将.forEeach替换为forEachOrdered - Misha

6
Arrays.stream(httpsServletRequest.getCookies())
    .filter(cookie -> CookieSession.NAME.equals(cookie.getName()))
    .forEach(cookie -> {
        cookie.setValue(null); 
        cookie.setMaxAge(0); 
        cookie.setPath("/");
        httpServletResponse.addCookie(cookie); 
    });

5
< p > for 循环可以被替换为 forEach 表达式:

Arrays.stream(cookies)
      .filter(c -> c.getName().equals(CookieSession.NAME))
      .forEach(c -> {c.setValue(null);
                     c.setMaxAge(0);
                     c.setPath("/");
                     httpServletResponse.addCookie(c);
                    });

5
其他答案似乎忽略了 if (cookies != null)。此外,我喜欢使用peek进行多个中间操作而不是一个块。对我来说更清晰。
Optional.ofNullable(httpServletRequest.getCookies())
    .ifPresent(cookies -> Arrays.stream(cookies)
        .filter(cookie -> cookie.getName().equals(CookieSession.NAME))
        .peek(cookie -> cookie.setValue(null))
        .peek(cookie -> cookie.setMaxAge(0))
        .peek(cookie -> cookie.setPath("/"))
        .forEach(httpServletResponse::addCookie));

4

使用lambda或forEach无法简化此操作。

此外,许多人认为不应该在像这样的一行中使用forEach来改变状态:

cookies.forEach(cookie -> httpServletResponse.addCookie(cookie));

然而,这只是一种风格问题。只要forEach按顺序(而不是并行)消耗元素,实际上没有任何可能导致错误的情况发生。 这里是Oracle在这个问题上的建议。 我认为,你应该保留你的代码不变。

我担心你关于Oracle建议的陈述可能会误导一些读者。在forEach中修改状态并不会有任何不安全的问题。你提供的链接是为了阐述使用forEach的风格原因,以此作为不考虑使用映射和归约的更好的函数解决方案的证据。 - sprinter
1
谢谢您的编辑。为避免混淆,我会删除我的原始评论。实际上,我同意您关于新版本是否更好的观点。但似乎世界正变得更加函数化,所以我们最好还是适应一下 :-) - sprinter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接