How can I reverse a single String in Java 8 using Lambda and Streams?
Asked Answered
R

19

21

I have one string say "Aniruddh" and I want to reverse it using lambdas and streams in Java 8. How can I do it?

Rattler answered 27/11, 2017 at 5:58 Comment(4)
a) What have you tried so far? b) Are you trying to re-invent the wheel?Dupondius
Why do you insist on lambdas and streams?Assured
Hello and welcome! It might be worth having a look at this article which has some tips on how to ask a great question that'll get you the answer you're looking for.Laevogyrate
Why to invent Wheel again? Cannot use library function??Turku
T
46

Given a string like

String str = "Aniruddh";

the idiomatic solution is

String reversed = new StringBuilder(str).reverse().toString();

If, perhaps for educational purposes, you want to solve this by streaming over the string’s characters, you can do it like

String reversed = str.chars()
    .mapToObj(c -> (char)c)
    .reduce("", (s,c) -> c+s, (s1,s2) -> s2+s1);

This is not only much more complicated, it also has performance drawbacks.

The following solution eliminates boxing related overhead

String reversed = str.chars()
    .collect(StringBuilder::new,
             (b, c) -> b.insert(0, (char)c), (b1, b2) -> b1.insert(0, b2))
    .toString();

but is still less efficient because inserting into the beginning of an array based buffer implies copying all previously collected data.

The bottom line is, for real applications, stay with the idiomatic solution shown at the beginning.

Tashia answered 27/11, 2017 at 14:49 Comment(4)
ingenious way via reduce :)Comitative
I believe you mean "idiomatic", as opposed to "canonical". I don't believe abstraction can be deemed canonical.Joscelin
@Joscelin yes, today, I’d rather use the word “idiomatic” here.Tashia
@Holger, lol! Despite that, great answer, +1.Joscelin
S
8

Try this for reverse a string using lambda and streams

import java.util.stream.Stream;
import java.util.stream.Collectors;

    public class Test  {


        public static void main(String[] args) {

            System.out.println(reverse("Anirudh"));;
        }
        public static String reverse(String string) {
            return Stream.of(string)
                .map(word->new StringBuilder(word).reverse())
                .collect(Collectors.joining(" "));
        }
    }
Steelhead answered 27/11, 2017 at 6:4 Comment(1)
kind of a testament to @satya's point... do we really need to use streams or lamdas in this case when new StringBuilder(word).reverse() provides the desired effect? IMHO, this is over engineeredCoastward
C
4

If you really want to do it for learning purposes, why not reverse the char array?

public static String reverse(String test) {
    return IntStream.range(0, test.length())
            .map(i -> test.charAt(test.length() - i - 1))
            .collect(StringBuilder::new, (sb, c) -> sb.append((char) c), StringBuilder::append)
            .toString();
}
Comitative answered 27/11, 2017 at 12:13 Comment(0)
C
2

Another approach to reversing your String. You can use an IntStream to pull the correct character out of a char array.

public static void main(String[] args) {
    char[] charArray = "Aniruddh".toCharArray();
    IntStream.range(0, charArray.length)
        .mapToObj(i -> charArray[(charArray.length - 1) - i])
        .forEach(System.out::print);
}
Coastward answered 27/11, 2017 at 6:36 Comment(0)
O
2

Another alternative way would be to split the string into an array of string and use reduce() on it.

Stream.of("Aniruddh".split("")).reduce("", (reversed, character) -> character + reversed);
Okeefe answered 7/1, 2020 at 4:19 Comment(1)
This is the best answer if you don't intend to use String BuilderAdaline
H
1
Function<String, String> reverse = s -> new StringBuilder(s).reverse().toString();
Hassiehassin answered 13/10, 2019 at 8:50 Comment(2)
Even if this is a valid answer, you'd better comment on what is going on and explain a bit of your code.Kilter
Please explain your answer.Pend
F
1

Here is another way, doesn't seem super efficient but will explain why:

String s = "blast";
IntStream.range(0, s.length()).           // create index [0 .. s.length - 1] 
   boxed().                               // the next step requires them boxed
   sorted(Collections.reverseOrder()).    // indices in reverse order
   map(i -> String.valueOf(s.charAt(i))). // grab each index's character 
   collect(Collectors.joining());         // join each single-character String into the final String

It would be better if there was a way to append all the Characters without converting each to String and then joining them. That's why I said it doesn't seem super efficient.

Flatfish answered 3/12, 2019 at 22:44 Comment(1)
Sorting is redundant, you can generate a descending sequence of indices instead IntStream.iterate(s.length() - 1, i -> i >= 0, i -> --i).Sixgun
A
1
String str = "Noorus Khan";
       int len = str.length();
        IntStream.range(0, len)
                .map(i -> len - 1 - i)
                .mapToObj(j->str.charAt(j))
                .forEach(System.out::print);

output :: nahK surooN

Aspirate answered 1/11, 2021 at 20:29 Comment(0)
A
1

You can use the below technique to reverse a string using stream.

String str = "Aniruddh";

Stream.iterate(str.length()-1, n-> n >= 0, n-> n-1)
        .map(input::charAt)
        .forEach(System.out::print);
Auld answered 10/3, 2022 at 16:17 Comment(0)
D
1

One more approach could be writing a custom comparator (this could help reverse any element in collection/array) which would always return "-1"."-1" being whenever 2 objects are compared the second object will be prior to first in placing order.

    Comparator<String> comparator = (s1,s2) -> -1;
    
    String reversed = Arrays.stream(input.split(""))
                           .sorted(comparator)
                           .collect(Collectors.joining());
            
Daric answered 15/5, 2023 at 13:4 Comment(0)
E
0

The easiest way to achieve what you're asking using streams is probably this:

String result = Stream.of("Aniruddh").map(__ -> "hddurinA").findFirst().get();
Espagnole answered 27/11, 2017 at 12:20 Comment(0)
F
0

Given a String of length S, reverse the whole string without reversing the individual words in it. Words are separated by dots.

String str="abcd.efg.qwerty";

String reversed = Arrays.asList(str.split("\\.")).stream().map(m -> new 
StringBuilder(m).reverse().toString()).collect(Collectors.joining("."));

System.out.println(reversed);
Favian answered 17/2, 2020 at 19:18 Comment(0)
L
0

Following is another approach to reverse the input String str using Java 8 streams API.

String abc = Arrays.asList(str).stream()
    .map(s -> new StringBuilder(s).reverse().toString())
    .collect(Collectors.toList()).get(0);
Levin answered 30/1, 2022 at 20:48 Comment(0)
S
0

A custom collector can be handy if you want to achieve it with Stream API (I'm treating this task exclusively as an exercise).

Since none of the contributors of this question mentioned this possibility, here's a brief description of how to do that.

Creating a Custom Collector

You can create a custom collector either inline by using one of the versions of the static method Collector.of() or by creating a class that implements the Collector interface.

enter image description here

  • Supplier Supplier<A> is meant to provide a mutable container which store elements of the stream. It could be a Collection, StringBuilder or any other mutable object.
  • Accumulator BiConsumer<A,T> defines how to add elements into the container provided by the supplier.
  • Combiner BinaryOperator<A> combiner() establishes a rule on how to merge two containers in case of parallel execution.
  • Finisher Function<A,R> is meant to produce the final result by transforming the mutable container.
  • Characteristics allows to provide additional information, for instance Collector.Characteristics.UNORDERED signifies that the collector does not guarantee to preserve initial order of elements when the source of the stream is ordered, which can provide better performance in parallel.

The minimum set of parameters boils down to supplier, accumulator and combiner which resembles the arguments of collect() operation with one difference - combiner argument expected by of() (as well as the return type of the combiner() method) is BinaryOperator<A>.

Implementations

The idea behind the first collector is to use ArrayDeque as a mutable container and add each element from the stream of code points to the front of the deque.

Portions of tasks created in parallel will result into several deques has to be combined in reversed order. Therefore, in the combiner the left deque (containing values from closer to the start of the source string) gets appended to the right deque (containing values from closer to the end of the source string), and the right deque is being returned as a result.

Finisher produces an array int[] of code point and returns a string based on it.

Collector<Integer, Deque<Integer>, String>

String source = "abcdefgh";

String reversed = source.codePoints()
    .boxed()
    .collect(Collector.of(
        ArrayDeque::new,
        Deque::addFirst,
        (Deque<Integer> left, Deque<Integer> right) -> { right.addAll(left); return right; },
        (Deque<Integer> deque) -> new String(
            deque.stream().mapToInt(Integer::intValue).toArray(),
            0,
            deque.size())
    ));

The second collector utilizes char[] as its mutable container which is being populated according to the indices of the source IntStream.

Combiner merges two arrays by peek the largest value for each position of the array.

Finisher utilizes constructor new String(char[]) to generate the resulting string.

Collector<Integer, char[], String>

String reversed = IntStream.range(0, source.length())
    .boxed()
    .collect(Collector.of(
        () -> new char[source.length()],
        (char[] arr, Integer i) -> arr[(source.length() - 1) - i] = source.charAt(i),
        (char[] left, char[] right) -> {
            for (int i = 0; i < left.length; i++) left[i] = (char) Math.max(left[i], right[i]); return left;
        },
        String::new
    ));

Output (for string "abcdefgh")

hgfedcba
Sixgun answered 18/4, 2022 at 3:7 Comment(0)
C
0
  public static String reverseStreams(String ex)
  {
    char[] charray=ex.toCharArray();
    StringWriter str=new StringWriter();
      IntStream.range(0, charray.length)
        .mapToObj(i->(charray[(charray.length-1)-i]))
     //   .collect(Collectors.toList())
        
        .forEach(s->str.append(s));
        return str.toString();
        
    
    

   }
Cowlick answered 19/2, 2023 at 17:35 Comment(1)
Code-only answers are considered low quality: make sure to provide an explanation what your code does and how it solves the problem. It will help the asker and future readers both if you can add more information in your post. See also Explaining entirely code-based answers: meta.stackexchange.com/questions/114762/…Prophase
M
0
public static void main(String[] args) {
    String str = "I am Vishwa Ratna";
    String[] split = str.split("");
    int len = str.length();
    String collect = IntStream.range(0, len).mapToObj(s -> {
        int k = len - 1;
        String sq = "";
        sq = split[k - s];
        --k;
        return sq;

    }).collect(Collectors.joining(""));
    System.out.println(collect);
}

First you convert your String to String array then you iterate through it in reverse order using Intstream and then you collect your stream to string by joining.

Maryammaryann answered 19/4, 2023 at 10:14 Comment(0)
L
0

The simple Approach I used is

String str = "INDIA";
    IntStream.range(0, str.length()).forEach(i -> System.out.print(str.charAt(str.length() - 1 - i)));
Lakin answered 31/8, 2023 at 12:12 Comment(0)
T
0
String str = "abc";
StringBuilder result = new StringBuilder("");
Stream.of(str.split("")).forEach(c -> result.insert(0,c));
Tweeze answered 1/9, 2023 at 7:31 Comment(1)
Please read How to Answer and edit your answer to contain an explanation as to why this code would actually solve the problem at hand. Always remember that you're not only solving the problem, but are also educating the OP and any future readers of this post.Fruin
S
0
String input = "Aniruddh";
String reverse = IntStream.range(0, input.length())
                    .mapToObj(i -> String.valueOf(input.charAt(input.length() - 1 - i)))
                    .collect(Collectors.joining());
Serranid answered 9/6 at 9:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.