Given a list
List l = new ArrayList();
l.add(\"one\");
l.add(\"two\");
l.add(\"three\");
I have a method
<With Java 8, you can use streams with joiners.
Collection<String> strings;
...
String commaDelimited = strings.stream().collect(Collectors.joining(","));
// use strings.parallelStream() instead, if you think
// there are gains to be had by doing fork/join
In Java 8 you can use String.join() like following:
Collection<String> elements = ....;
String result = String.join(", ", elements);
To produce grammatical output in English there are 3 cases to consider when concatenating a list of strings:
"A"
"A and B"
"A, B, and C.
This can be accomplished using standard Java or Guava like below. The solutions are basically the same and just up to preference what you want to use.
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import org.junit.Test;
import java.util.List;
import static org.junit.Assert.assertEquals;
public class JoinListTest {
@Test
public void test_join() {
// create cases (don't need to use ImmutableList builder from guava)
final List<String> case1 = new ImmutableList.Builder<String>().add("A").build();
final List<String> case2 = new ImmutableList.Builder<String>().add("A", "B").build();
final List<String> case3 = new ImmutableList.Builder<String>().add("A", "B", "C").build();
// test with standard java
assertEquals("A", joinListGrammaticallyWithJava(case1));
assertEquals("A and B", joinListGrammaticallyWithJava(case2));
assertEquals("A, B, and C", joinListGrammaticallyWithJava(case3));
// test with guava
assertEquals("A", joinListGrammaticallyWithGuava(case1));
assertEquals("A and B", joinListGrammaticallyWithGuava(case2));
assertEquals("A, B, and C", joinListGrammaticallyWithGuava(case3));
}
private String joinListGrammaticallyWithJava(final List<String> list) {
return list.size() > 1
? String.join(", ", list.subList(0, list.size() - 1))
.concat(String.format("%s and ", list.size() > 2 ? "," : ""))
.concat(list.get(list.size() - 1))
: list.get(0);
}
private String joinListGrammaticallyWithGuava(final List<String> list) {
return list.size() > 1
? Joiner.on(", ").join(list.subList(0, list.size() - 1))
.concat(String.format("%s and ", list.size() > 2 ? "," : ""))
.concat(list.get(list.size() - 1))
: list.get(0);
}
}
I like using Guava for this purpose. Neat and very useful:
Joiner.on(",").join(myList)
This kind of code has been written time and time again and you should rather be freed implementing your specific implementation logic.
If you use maven, herewith the dependency:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.1-jre</version>
</dependency>
It has a bunch of other wonderful cool features too!
This will produce the string "one, two, and three".
List<String> originalList = Arrays.asList("one", "two", "three");
Joiner.on(", ")
.join(originalList.subList(0, originalList.size() - 1))
.concat(", and ")
.concat(originalList.get(originalList.size() - 1));
Improved version from Bohemian♦'s answer. You can choose to remove the nulled items check on personal preferences.
/** Auto Concat Wrapper
* Wraps a list of string with comma and concat the last element with "and" string.
* E.g: List["A", "B", "C", "D"] -> Output: "A, B, C and D"
* @param elements
*/
public static String join(List<String> elements){
if(elements==null){return "";}
List<String> tmp = new ArrayList<>(elements);
tmp.removeAll(Collections.singleton(null)); //Remove all nulled items
int size = tmp.size();
return size == 0 ? "" : size == 1 ? tmp.get(0) : String.join(", ", tmp.subList(0, --size)).concat(" and ").concat(tmp.get(size));
}
Test results:
List<String> w = Arrays.asList("A");
List<String> x = Arrays.asList("A", "B");
List<String> y = Arrays.asList("A", "B", null, "C");
List<String> z = Arrays.asList("A", "B", "C", "D");
System.out.println(join(w));//A
System.out.println(join(x));//A and B
System.out.println(join(y));//A, B and C
System.out.println(join(z));//A, B, C and D
I don't know any Apache String joiner that can support adding and in the joined String.
Here's an untested code that will do what you asked:
public static String join(String separator, List<String> mList, boolean includeAndInText) {
StringBuilder sb = new StringBuilder();
int count = 0;
for (String m: mList) {
if (includeAndInText && (count + 1 != mList.size())) {
sb.append (" and ");
}
sb.append(m);
count++;
if (count < mList.size()) {
sp.append(separator);
}
}
return sb.toString();
}