[英]How can I reverse a single String in Java 8 using Lambda and Streams?
我有一个字符串说"Aniruddh"
,我想在 Java 中使用 lambda 和流来反转它 8. 我该怎么做?
给定一个字符串
String str = "Aniruddh";
规范的解决方案是
String reversed = new StringBuilder(str).reverse().toString();
如果,也许出于教育目的,您想通过流式传输字符串的字符来解决此问题,您可以这样做
String reversed = str.chars()
.mapToObj(c -> (char)c)
.reduce("", (s,c) -> c+s, (s1,s2) -> s2+s1);
这不仅要复杂得多,而且还有很多性能缺陷。
以下解决方案消除了与拳击相关的开销
String reversed = str.chars()
.collect(StringBuilder::new, (b,c) -> b.insert(0,(char)c), (b1,b2) -> b1.insert(0, b2))
.toString();
但效率仍然较低,因为插入基于数组的缓冲区的开头意味着复制所有先前收集的数据。
所以底线是,对于实际应用程序,保持在开头显示的规范解决方案。
尝试使用 lambda 和流反转字符串
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(" "));
}
}
如果你真的想为了学习而这样做,为什么不反转 char 数组呢?
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();
}
另一种反转字符串的方法。 您可以使用 IntStream 从char
数组中提取正确的字符。
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);
}
使用流实现您所要求的最简单方法可能是:
String result = Stream.of("Aniruddh").map(__ -> "hddurinA").findFirst().get();
Function<String, String> reverse = s -> new StringBuilder(s).reverse().toString();
这是另一种方式,看起来效率不高,但会解释原因:
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
如果有一种方法可以附加所有字符而不将每个字符转换为String
然后加入它们会更好。 这就是为什么我说它看起来效率不高。
您可以使用以下技术使用 stream 反转字符串。
String str = "Aniruddh";
Stream.iterate(str.length()-1, n-> n >= 0, n-> n-1)
.map(input::charAt)
.forEach(System.out::print);
另一种替代方法是将字符串拆分为字符串数组并在其上使用 reduce()。
Stream.of("Aniruddh".split("")).reduce("", (reversed, character) -> character + reversed);
给定一个长度为 S 的字符串,反转整个字符串而不反转其中的单个单词。 单词用点分隔。
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);
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);
输出 :: nahK surooN
以下是使用 Java 8 流 API 反转输入字符串str
的另一种方法。
String abc = Arrays.asList(str).stream()
.map(s -> new StringBuilder(s).reverse().toString())
.collect(Collectors.toList()).get(0);
如果你想用Stream API实现自定义收集器,它会很方便(我将此任务专门视为练习)。
由于这个问题的贡献者都没有提到这种可能性,这里简要说明如何做到这一点。
您可以通过使用 static 方法Collector.of()
的版本之一内联或通过创建实现Collector
接口的class
来创建自定义收集器。
Supplier<A>
旨在提供一个可变容器,用于存储 stream 的元素。它可以是Collection
、 StringBuilder
或任何其他可变 object。BinaryOperator<A> combiner()
建立了在并行执行的情况下如何合并两个容器的规则。Function<A,R>
旨在通过转换可变容器来产生最终结果。Collector.Characteristics.UNORDERED
表示收集器不保证在 stream 的源被排序时保留元素的初始顺序,这可以提供更好的并行性能。 最小参数集归结为supplier 、 accumulator和combiner ,它们类似于collect()
操作的 arguments ,但有一个区别 - of()
期望的 combiner 参数(以及combiner()
方法的返回类型)是BinaryOperator<A>
。
第一个收集器背后的想法是使用ArrayDeque
作为可变容器,并将代码点stream 中的每个元素添加到deque的前面。
并行创建的部分任务将导致必须以相反的顺序组合多个双端队列。 因此,在组合器中,左双端队列(包含更接近源字符串开头的值)被附加到右双端队列(包含更接近源字符串末尾的值),而右双端队列作为结果。
Finisher 生成代码点数组int[]
并返回基于它的字符串。
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())
));
第二个收集器使用char[]
作为其可变容器,该容器根据源IntStream
的索引进行填充。
Combiner通过查看数组中每个position的最大值来合并两个arrays。
Finisher 使用构造函数new String(char[])
生成结果字符串。
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 (对于字符串"abcdefgh"
)
hgfedcba
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.