I have one string say "Aniruddh"
and I want to reverse it using lambdas and streams in Java 8. How can I do it?
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.
reduce
:) –
Comitative 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(" "));
}
}
new StringBuilder(word).reverse()
provides the desired effect? IMHO, this is over engineered –
Coastward 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();
}
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);
}
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);
Function<String, String> reverse = s -> new StringBuilder(s).reverse().toString();
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.
IntStream.iterate(s.length() - 1, i -> i >= 0, i -> --i)
. –
Sixgun 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
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);
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());
The easiest way to achieve what you're asking using streams is probably this:
String result = Stream.of("Aniruddh").map(__ -> "hddurinA").findFirst().get();
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);
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);
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.
- Supplier
Supplier<A>
is meant to provide a mutable container which store elements of the stream. It could be aCollection
,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
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();
}
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
.
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)));
String str = "abc";
StringBuilder result = new StringBuilder("");
Stream.of(str.split("")).forEach(c -> result.insert(0,c));
String input = "Aniruddh";
String reverse = IntStream.range(0, input.length())
.mapToObj(i -> String.valueOf(input.charAt(input.length() - 1 - i)))
.collect(Collectors.joining());
© 2022 - 2024 — McMap. All rights reserved.