Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Concatenating strings with RxJava2

I have a simple List of my POJO called Sport which has a name field . What is the best way to concat all the names in the List?

Observable.just(member.getSports())
          .map(sports -> {
              StringBuilder builder = new StringBuilder();
              for (Sport sport : sports) {
                  builder.append(sport.getName());
              }
              return builder.toString()
           })

I believe there must be a better way ?

like image 405
Muhammad Ahmed AbuTalib Avatar asked Apr 20 '26 06:04

Muhammad Ahmed AbuTalib


2 Answers

Willi Mentzel is right that you don't need Rx, but if you want to use it anyway in plain Java for readability, here's a cool way to leverage Rx2

// Get a list of sports names
Observable<String> names = Observable.fromIterable(member.getSports()).map(sport -> sport.getName())

// Concat list into a single string output separated by comma
Single<String> listOfNames = names.collect(StringBuilder::new, (sb, x) -> sb.append(x).append(", ")).map(StringBuilder::toString).toSingle()

One-liner in Java:

Observable.fromIterable(member.getSports()).map(sport -> sport.getName()).collect(StringBuilder::new, (sb, x) -> sb.append(x).append(", ")).map(StringBuilder::toString).toSingle()

One-liner in Kotlin with RxKotlin

member.getSports().map { it.name }.toObservable().collect(StringBuilder::new, (sb, x) -> sb.append(x).append(", ")).map(StringBuilder::toString).toSingle()

Produces:

volleyball, hockey, racquetball

You should always strive for code that is easy to read and therefore to maintain.

You don't need RxJava for that, just streams:

String joined = member.getSports().stream()
            .map(sport -> sport.getName())
            .collect(Collectors.joining(""));

Edit 1:

Since streams are not an option. I wouldn't use RxJava then anyways. Just use the code from inside your lambda.

StringBuilder builder = new StringBuilder();
for (Sport sport : sports) {
   builder.append(sport.getName());
}
builder.toString()

Edit 2: Or you build a more generalized version, in case you need a prefix and postfix as well:

// Inside Utils.java
public static <T> String joinToString(List<T> list, String separator, String prefix, String postfix, Function<T, String> func) {
    StringBuilder builder = new StringBuilder();

    builder.append(prefix);

    if (!list.isEmpty()) {
        for (T t : list.subList(0, list.size() - 1)) {
            builder.append(func.apply(t));
            builder.append(separator);
        }

        builder.append(list.get(list.size() - 1));
    }

    builder.append(postfix);
    return builder.toString();
}

and use it like this:

Utils.joinToString(member.getSports(), "", "", "", Sport::getName));

This comes pretty close to Kotlin's joinToString extension function.

like image 35
Willi Mentzel Avatar answered Apr 22 '26 02:04

Willi Mentzel



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!