1

I am new to Java 8 and looking to implement below in Java 8 only.

I have the following numbers

1111
2222
3333
4444

I want to convert all these numbers like '1111','2222','3333','4444' The list of numbers can be anything and it should be dynamic

I developed code like below, but only servers half purpose

List<String> numbers = Arrays.asList("111", "2222", "3333", "4444");
        String collect = numbers.stream().map(n -> n).collect(Collectors.joining(",'"));
        System.out.println(collect);

Output:

111,'2222,'3333,'4444
Ousmane D.
  • 54,915
  • 8
  • 91
  • 126
Jeff Cook
  • 7,956
  • 36
  • 115
  • 186
  • Read the javadoc: https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#joining-java.lang.CharSequence-java.lang.CharSequence-java.lang.CharSequence-. Also, what do you think map(n -> n) does? – JB Nizet Sep 27 '18 at 18:57

3 Answers3

2

Simply like this:

List<String> numbers = Arrays.asList("111", "2222", "3333", "4444");
String collect = numbers.stream().map(n -> "'" + n + "'").collect(Collectors.joining(","));
System.out.println(collect);
NiVeR
  • 9,644
  • 4
  • 30
  • 35
  • That's the correct way of doing it, but there is also the ghetto way: `String collect = "'" + numbers.stream().collect(Collectors.joining("','")) + "'";` (why ghetto? because it's bad design and it won't work properly with 0 length array) – kajacx Sep 27 '18 at 19:16
  • @kajacx If you have an alternative solution, it would be better to post it as an answer, than as a comment under someone else's answer. – Dawood ibn Kareem Sep 27 '18 at 19:17
  • Nah, as I said: it is a bad solution, I just commented it for fun and to see the comparision between good and bad design, not because people should use it. – kajacx Sep 27 '18 at 19:22
  • 2
    @kajacx or even `joining("', '", "'", "'")`. – Andy Turner Sep 27 '18 at 19:26
  • 1
    @AndyTurner well that’s preferable if you can preclude empty streams. – Holger Sep 28 '18 at 11:23
1

For the fun of it, using a StringBuilder and a custom collector:

String result = Arrays.asList("111", "2222", "3333", "4444")
            .stream()
            .collect(Collector.of(
                    StringBuilder::new,
                    (sb, s) -> sb.append('\'').append(s).append('\'').append(","),
                    StringBuilder::append,
                    sb -> {
                        sb.setLength(Math.max(0, sb.length() - 1));
                        return sb.toString();
                    }));
Eugene
  • 117,005
  • 15
  • 201
  • 306
  • 1
    The collector "contructor" accepts a finalization method as an optional 4th argument? I never knew that, +1 for random usefull info. – kajacx Sep 27 '18 at 19:20
  • Isn't this just a "bit" unefficient? – NiVeR Sep 27 '18 at 19:29
  • Can't you just return `sb.toString()` from the finalizer? – Andy Turner Sep 27 '18 at 19:31
  • @Eugene "return sb.toString()" after trimming the comma. – Andy Turner Sep 27 '18 at 19:36
  • @NiVeR inefficient? exactly how plz? – Eugene Sep 27 '18 at 19:40
  • First of all code-wise, and probably also computationally (though is not easy to say exactly). – NiVeR Sep 27 '18 at 19:50
  • @NiVeR it actually should outperform `StringJoiner` and thus your solution easily. – Eugene Sep 27 '18 at 19:53
  • Extracting the Collector.of..., the sb ->{} lambda parts to separate methods will surely make it more readable. It's surely more "efficient" memory wise but doesn't read very fluently :/ – Sneh Sep 27 '18 at 20:13
  • @Sneh *to you* it's not; it's an entire different story after 3 years with java-8... – Eugene Sep 27 '18 at 20:14
  • I'm pretty sure that a normal `for` loop is still faster than streams, so you should use that if performance is critical, while you should use streams where you can afford to be 2-3 times (I'm guessing) slower for the sake of code readibility. – kajacx Sep 28 '18 at 08:52
  • @kajacx [see here](https://stackoverflow.com/a/49466784/1059372) or [this one](https://stackoverflow.com/a/48624167/1059372) . when playing with concat and String, `StringBuilder` is still the one to go with; and the second point - streams are not slower (they are by a fraction) once code is hot enough – Eugene Sep 28 '18 at 09:00
  • 1
    Keep in mind that streams may be empty. Besides that, you’ve just re-invented the `StringJoiner` and `joining` collector… – Holger Sep 28 '18 at 11:21
  • @Holger by accident I did, just looked up the sources today in detail – Eugene Sep 28 '18 at 11:22
  • @Eugene my point was that if you joined the strings together with a StringBuilder in a for loop it would be faser than using a stream. The first link you provided has no info on this comaprision whatsoever, while the second link has much more additional stuff like taking only strings of certain length or taking only unquie strings, so the results are not that usefull. Also, what do you mean "once code is hot enough"? – kajacx Sep 29 '18 at 10:53
0
String numbers = Arrays.asList("111", "2222", "3333", "4444").stream()
    .map(number -> "'" + number + "'")
    .collect(Collectors.joining(",")));

This will give you

"111,'2222,'3333,'4444"

As suggested in comments, you can also do it by directly creating a stream with the numbers rather than making a list and then a stream.

Stream.of("111", "2222", "3333", "4444")
        .map(number -> "'" + number + "'")
        .collect(Collectors.joining(",")));
Sneh
  • 3,527
  • 2
  • 19
  • 37
  • 1
    `Arrays.asList("111", "2222", "3333", "4444").stream()` is better off as `Stream.of("111", "2222", "3333", "4444")...` – Ousmane D. Sep 27 '18 at 19:17
  • I know but tried to keep it same as what OP posted. :) I will edit my answer anyway. – Sneh Sep 27 '18 at 19:18