【问题标题】:Converting Array iteration to lambda expression将数组迭代转换为 lambda 表达式
【发布时间】:2016-04-10 05:54:32
【问题描述】:

我有下面的代码迭代 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 表达式来简化它

【问题讨论】:

  • 是的。但您可以先修复 if 条件中缺少 {} 的问题
  • 不是,不是。它不会被简化;它会基本相同,但有点复杂。
  • Lambda 不会让这变得更简单。更慢,更占用内存,但并不简单。

标签: java lambda java-8


【解决方案1】:

不确定是否会简化,但可以,是的:

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

【讨论】:

  • 从技术上讲,它并不等同,因为 OP 的代码缺少括号,并且只有第一个 setter 将取决于 if... 但无论如何您的代码都符合他的期望。
  • 值得指出的是,仍然需要做空检查。如果没有 cookie,httpServletRequest.getCookies() 将返回 null 并且 Arrays.stream 不能容忍空值。另外,由于HttpServletResponse 未指定为线程安全的,所以.forEeach 最好替换为forEachOrdered
【解决方案2】:
Arrays.stream(httpsServletRequest.getCookies())
    .filter(cookie -> CookieSession.NAME.equals(cookie.getName()))
    .forEach(cookie -> {
        cookie.setValue(null); 
        cookie.setMaxAge(0); 
        cookie.setPath("/");
        httpServletResponse.addCookie(cookie); 
    });

【讨论】:

    【解决方案3】:

    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);
                        });
    

    【讨论】:

      【解决方案4】:

      其他答案似乎忽略了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));
      

      【讨论】:

        【解决方案5】:

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

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

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

        不过,这确实是风格问题。只要forEach 按顺序(而不是并行)使用元素,就不会因为这样的一行而实际出错。

        Here is Oracle's advice on the subject.

        在我看来,你应该保留你的代码。

        【讨论】:

        • 我担心您关于 Oracle 建议的陈述可能会误导一些读者。在forEach 中修改状态并没有什么不安全的地方。您提供的链接反对使用 forEach 出于文体原因 - 提供证据表明没有考虑使用映射和归约的更好的功能解决方案。
        • 感谢您的编辑。我将删除我的原始评论以避免混淆。我实际上同意你关于新版本是否更好的观点。但似乎世界正在运转,所以我们最好习惯它:-)
        猜你喜欢
        • 1970-01-01
        • 2012-01-15
        • 1970-01-01
        • 2017-09-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多