StringJoiner - each item in parenthesis

Viewed 270

To fit a SQL template in a Java app, I need to format elements as follows:

RIGHT JOIN (values (123), (456), (789)..

In particular, given a Java list of integers:

List<int> ints = Arrays.asList(123, 456, 789)

How can I correctly use StringJoiner (examples) to output the following string?

(123), (456), (789)

The closest example I can find is

StringJoiner mystring = new StringJoiner(",", "(", ")");    

Which returns

(123, 456, 789)

More Background/Context

MadProgrammer pointed out that I may approach this differently via PreparedStatement. Here is the actual query I'm trying to fill...

So for example, here is a snippet of the query in native SQL:

SELECT loadlist.id as load_id, payload
FROM payload_log
     RIGHT JOIN (values (123), (456), (789)) as loadlist(id)
            ON payload_log.entity_id = loadlist.id;

And here is how it's being called from application. Ideally we could bind using the :ids parameter, but not sure how so was going to do String.format w/ the joiner.

String queryString = String.format("SELECT loadlist.id as load_id, payload\n"+
        "FROM payload_log" +
        "     RIGHT JOIN (values (:ids)) as loadlist(id)" +
        "          ON payload_log.entity_id = loadlist.id)";
return entityManager.createNativeQuery(queryString).setParameter("ids", loadIds);

Now I should be able to pass the :ids parameter using query.setParameter after applying formatting as in answers below? So where does a PreparedStatement fit in?

4 Answers

With your existing code, the easiest way is to add the parentheses to your separator:

StringJoiner mystring = new StringJoiner("), (", "(", ")");
// add...
// (123), (456), (789)

Or just use the collector:

String s = Arrays.asList(123, 456, 789)
    .stream()
    .map(Object::toString)
    .collect(Collectors.joining("), (", "(", ")"));
// (123), (456), (789)

Better to use prepared statements though instead of using string manipulation to build queries.

With StringJoiner

        List<Integer> ints = Arrays.asList(123, 456, 789);
        StringJoiner mystring = new StringJoiner("),(", "(", ")");
        ints.forEach(i -> mystring.add(String.valueOf(i)));
        
        System.out.println( mystring );

With java Collectors.joinig():

List<Integer> ints = Arrays.asList(123, 456, 789);
ints.stream().map(i -> "(" + String.valueOf(i) + ")").collect(Collectors.joining(","));

You can use the Stream API to map each number to a string, ( n ) and then collect the Stream using Collectors#joining with , as the delimiter.

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    public static void main(String args[]) {
        List<Integer> ints = Arrays.asList(123, 456, 789);

        String result = ints.stream().map(n -> "(" + String.valueOf(n) + ")").collect(Collectors.joining(", "));

        System.out.println(result);
    }
}

Output:

(123), (456), (789)

Use PreapredStatement and positioned parameters. This should be your first port of call and will save you a lot of potential head aches.

Having said that, just for some fun...

List<Integer> ints = Arrays.asList(123, 456, 789);
String joined = ints.stream().map(x -> "(" + x + ")").collect(Collectors.joining(", "));
System.out.println(joined);

Prints (123), (456), (789)

Related