【问题标题】:join elements from forEach连接来自 forEach 的元素
【发布时间】:2018-11-11 15:46:30
【问题描述】:

我正在创建 SQL SELECT 查询字符串,方法是获取两个列表并并行迭代它们。

List<String> selectFields = new ArrayList<>();
List<String> uuidFunction = new ArrayList<>();
selectFields.add("id");
selectFields.add("name");

uuidFunction.add("UUID_TO_STR");
uuidFunction.add(null);

StringBuilder sql = new StringBuilder("SELECT ");

IntStream.range(0, selectFields.size())
        .parallel()
        .forEach(i -> {
          sql.append(
              uuidFunction.get(i) != null ? uuidFunction.get(i) + "(" + selectFields.get(i) + ")"
                  : selectFields.get(i));
        }
        );
sql.append(" FROM test_table"); 

这给了我一个很好的 SQL 字符串,但每个元素之间没有逗号 ,

选择名称UUID_TO_STR(id)

为什么我不能在 forEach 之后使用.collect(Collectors.joining(","))

注意这个问题是我的项目中一个更大的功能的一部分,其中没有使用直接的 SQL 准备语句。所以请不要提供解决这个问题的SQL方式。这是与迭代和附加字符串相关的一般问题。

【问题讨论】:

  • 我不太了解流,但我知道 SQL 注入,这是不使用语句生成查询的结果。请使用语句。
  • forEach 是没有返回值的终端操作。这就是为什么你不能收集它
  • 我唯一的解决方法是在 forEach 中附加带有 "," 的字符串,然后在退出 forEach sql.deleteCharAt(sql.length()-1) 后立即删除最后一个 ","。有更好的解决方案吗?
  • @TimBiegeleisen 实际上是Java's PreparedStatements don't handle column name selection,并给出了 OP 的评论,即查询构造是更大代码库的一部分,因为我们知道该字符串稍后可能会被馈送到 PreparedStatement。我承认我有同样的反应。
  • @Aaron 如果 OP 在没有外部输入的情况下构建查询,那么这里没有任何问题。如果有来自外部的输入,则对具有不同列/表的查询使用单独的语句。

标签: java string join java-stream stringbuilder


【解决方案1】:

.forEach() 之后无法收集,因为它是没有返回值 (void) 的终端操作。因此你无法收集。要使其工作,您可以使用以下 sn-p:

String sql = IntStream.range(0, selectFields.size())
    .mapToObj(i -> uuidFunction.get(i) != null 
         ? uuidFunction.get(i) + "(" + selectFields.get(i) + ")"
         : selectFields.get(i)
    )
    .collect(Collectors.joining(", ", "SELECT ", " FROM test_table");

请注意,带有 3 个参数的 joining 重载具有以下签名:

public static Collector<CharSequence, ?, String> joining(CharSequence delimiter,
                                                         CharSequence prefix,
                                                         CharSequence suffix){...}

【讨论】:

  • 我仍然无法理解它,但它可能只是我(我不是以英语为母语的人)。 “[...]分别是前缀和后缀”可能会更好?
  • @Aaron 我也没有。而且它确实听起来很奇怪。必须再次重写
  • 好吧,现在肯定没有任何歧义了:)
  • @Aaron 代码不言自明,努力解释一个简单的方法签名;)
  • 哦,对了。我认为,与更简单的 lambda 相比,我仍然更喜欢更少的代码重复,即.mapToObj(i -&gt; { String u=uuidFunction.get(i), s=selectFields.get(i); return u!=null? u+'('+s+')': s; })
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-31
相关资源
最近更新 更多