I need to join a list of strings with commas. But also I have a limit of line length.
For example list I need to join a list of strings with commas
should become :
I, need, to, join, a, \n list, of, strings, with, \n commas
.
I've already implemented a method for this:
private static String joinLabels(List<String> strings) {
int rowLengthCounter = 0;
StringBuilder result = new StringBuilder();
for (String str : strings) {
rowLengthCounter = str.length();
if (rowLengthCounter > 40) {
result.append("\n");
rowLengthCounter = str.length();
}
result.append(str);
result.append(", ");
}
return result.substring(0, result.lastIndexOf(", "));
}
And it works. But maybe simple method exists, like String.join to join strings with specified delimiter, or stream API. Thanks for help.
CodePudding user response:
The code is quite complicated with streams but you can write it like that :
public static String joinLabels2(final List<String> strings,) {
final Optional<String> res = strings.stream()
.map(s -> s ", ")
.reduce((s1, s2) ->
s1.contains("\n") && (s1 s2).length() - StringUtils.lastIndexOf(s1, "\n") > 40
||
!s1.contains("\n") && (s1 s2).length() > 40
?
s1 s2 "\n" : s1 s2)
.map(s -> s.substring(0, s.length() - 2));
return res.get();
}
Test by changing the max length from "40" to "10" :
@Test
public void test() {
System.out.println(joinLabels2(Arrays.asList("I", "need", "to", "join", "a", "list", "of", "strings", "with", "commas")));
}
outputs :
I, need, to,
join, a, list,
of, strings,
with, commas,
It would be great to write the reduce condition like that : (s1 s2).length() > 40 ? ...
but after the first line break the condition would be always true because s1 contains the previous reduction.
NB: you need to fine tune that method if you want to compare the length without commas because I added them before the reduction but you didn't in your original code.
CodePudding user response:
I would do something like this. It eliminates the counter, so that is one less moving part.
- Add commas to each string except the last one
- try to add each token to the
StringBuilder
- If adding next token to the the current line in the StringBuilder is more than max, add line break
- Add token
private static final int maxLength = 15;
private static final List<String> strings = Arrays.asList("I", "need", "to", "join", "a", "list", "of", "strings", "with", "commas");
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
IntStream.range(0, strings.size())
.mapToObj(i -> strings.get(i) (i<strings.size()-1 ? ", " : ""))
.forEach(s -> addToStringBuilder(s, sb));
System.out.println(sb);
}
private static void addToStringBuilder(String s, StringBuilder sb) {
int currentLineLength = sb.length() - sb.lastIndexOf("\n");
if (currentLineLength s.length() > maxLength) {
sb.append("\n");
}
sb.append(s);
}
Output:
I, need, to,
join, a,
list, of,
strings,
with, commas
CodePudding user response:
you can use java 8's stream and collectors api to do like this,
private static String joinLables(List<String> lables) {
final AtomicInteger counter = new AtomicInteger();
final Integer chunkSize = 3;
final String DELIMITER = ",";
return lables.stream()
.collect(Collectors.groupingBy(it -> counter.getAndIncrement() / chunkSize)).values()
.stream()
.map(s -> String.join(DELIMITER, s))
.reduce((a, b) -> a "\n" b)
.get();
}