Search code examples
javastringjoinjava-streamstringbuilder

join elements from forEach


I am creating SQL SELECT query String, by taking two lists and iterating over them in parallel.

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

This gives me a nice SQL String BUT without commans , between each element.

SELECT nameUUID_TO_STR(id)

Why can't I use .collect(Collectors.joining(",")) right after forEach ?

NOTE this problem is part of a bigger function in my Project where are are not using direct SQL Prepared Statements. So please don't provide SQL way of solving this problem. This is a generic problem related to iterations and appending Strings.


Solution

  • You can't collect after .forEach() because it's a terminal operation with no return value (void) . Thus you can't collect. For it to work you can use the following snippet:

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

    Note that the joining overload with the 3 parameters has following signature:

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