In JavaScript we can build a string with other types using reducer (e.g. num to string):
const string = [1,2,3,4,5].reduce((acc,e) => acc += e, "") //"12345"
In Java, this pattern is not as easy when building a string from other types:
ArrayList<Integer> arrayListOfIntegers = (ArrayList<Integer>) Arrays.asList(1,2,3,4);
String string = arrayListOfIntegers.stream().reduce("", (String acc, Integer e) -> acc += e); // acc += e throws error
The error is:
"Bad return type: String cannot be converted to integer"
Is this pattern not possible in Java?
In JavaScript we can build a string with other types using reducer (e.g. num to string):
const string = [1,2,3,4,5].reduce((acc,e) => acc += e, "") //"12345"
In Java, this pattern is not as easy when building a string from other types:
ArrayList<Integer> arrayListOfIntegers = (ArrayList<Integer>) Arrays.asList(1,2,3,4);
String string = arrayListOfIntegers.stream().reduce("", (String acc, Integer e) -> acc += e); // acc += e throws error
The error is:
"Bad return type: String cannot be converted to integer"
Is this pattern not possible in Java?
Share Improve this question edited Mar 30, 2021 at 5:33 mplungjan 178k28 gold badges181 silver badges240 bronze badges asked Mar 30, 2021 at 5:32 DavidDavid 1311 silver badge4 bronze badges 2-
Java is a strongly typed language where you can't just mash an integer into a string and expect the piler to know whether you mean concatenation or addition. Also, if you read the JavaDoc for
Stream.reduce
you'll see that all parameters involved must be of same type. So you need to map the Integer to a String before you can reduce it into a string. – Torben Commented Mar 30, 2021 at 5:41 -
3
Using
+=
is an obfuscation. Your actual intention is(acc, e) -> acc + e
but your choice to use+=
instead will lead to a pointless modification of theacc
parameter variable which will never be read again. Besides that, in Java you would needreduce("", (acc,e) -> acc + e, (s1,s2) -> s1 + s2)
. This works, but is horribly inefficient for streams with lots of elements. Usemap(String::valueOf).collect(Collectors.joining())
when you prefer simplicity, orcollect(StringBuilder::new, StringBuilder::append, StringBuilder::append) .toString()
for highest efficiency. – Holger Commented Mar 31, 2021 at 11:08
5 Answers
Reset to default 12In Java, you can simply collect the Stream using Collectors.joining
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<Integer> arrayListOfIntegers = Arrays.asList(1, 2, 3, 4);
String str = arrayListOfIntegers.stream().map(String::valueOf).collect(Collectors.joining());
System.out.println(str);
}
}
Output:
1234
Your are trying to reduce a list of Integers to a String
. First map those Integers to Strings and then reduce
:
List<Integer> list = Arrays.asList(1,2,3,4);
String value = list.stream()
.map(String::valueOf)
.reduce("", String::concat);
Instead of (acc,e) -> acc+e
you could use String::concat
. Also, the type is not pulsory in the lambda expression.
I suppose the best way is using Collectors.joining provided by @Thomas and @Arvind Kumar Avinash. But as a alternative solution I can suggest to use collect method and StringBuilder class, it doesn't generate new String object every time as in reduce case:
List<Integer> list = Arrays.asList(1,2,3,4);
String value =
list.stream()
.collect(StringBuilder::new, StringBuilder::append, StringBuilder::append)
.toString();
I suggested this code:
public static void main(String[] args) {
List<Integer> arrayListOfIntegers = Arrays.asList(1,2,3,4);
String string = arrayListOfIntegers.stream().reduce("",(sum,elm)-> sum += elm.toString(),(sum1,sum2) -> sum1+sum2);
System.out.println(string);
}
Among few other options, here is my contribution, when you have list of int i.e primitive values please use [IntStream][1]
here is how i have tried to do it. rangeClosed
is inclusive of the last number. mapToObj
is a intermediate and collect
is a terminal operation.
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class SampleIntStream {
public static void main(String[] args) {
System.out.println(getComposedString(1, 5));
}
public static String getComposedString(int from, int to) {
return IntStream
.rangeClosed(from, to)
.mapToObj(String::valueOf)
.collect(Collectors.joining());
}
}