[英]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.