如何使用java8流API按每个字符连接两个字符串?

问题描述 投票:0回答:2

我需要帮助解决这个问题,我有两个字符串

String s1 = "Mohan";
String s2 = "1234567";

我需要输出为

"M1o2h3a4n567"

就像 s1 第一个字符然后 s2 第一个字符。

如何使用 java8 流 API 解决这个问题?

我将两个字符串转换为一个列表,然后在流API中尝试使用reduce,但我知道这不是正确的解决方案。

java java-8 java-stream
2个回答
0
投票

如果你确实想使用流,你可以构造一个较短字符串索引的流,并将每个索引映射到一个由字符

s1.charAt(i)
s2.charAt(i)
组成的字符串,用
Collectors.joining()
将它们连接起来,然后添加任何内容较长字符串的左侧。

var shorterLength = Math.min(s1.length(), s2.length());
var result = IntStream.range(0, shorterLength).mapToObj(
        i -> s1.charAt(i) + String.valueOf(s2.charAt(i))
    ).collect(Collectors.joining())
    + s1.substring(shorterLength) + s2.substring(shorterLength);

也就是说,这会创建很多中间字符串。它为每一对字符创建一个新的字符串对象。

我宁愿不使用流,而只是使用

StringBuilder
命令式地执行此操作。没那么长了。

var sb = new StringBuilder();
for (int i = 0 ; i < shorterLength ; i++) {
    sb.append(s1.charAt(i)).append(s2.charAt(i));
}

if (s1.length() > shorterLength) {
    sb.append(s1.substring(shorterLength));
} else if (s2.length() > shorterLength) {
    sb.append(s2.substring(shorterLength));
}
// or just
// sb.append(s1.substring(shorterLength)).append(s2.substring(shorterLength));;
// if you don't care about creating an extra substring

var result = sb.toString();

0
投票

嗯,有很多选择,每种都有优点和缺点。

这是另一种方法,使用

IntStream
StringBuilder
:

String result = IntStream.range(0, Math.max(s1.length(), s2.length()))
    .collect(
            StringBuilder::new,
            (sb, i) -> {
                if (i < s1.length()) {
                    sb.append(s1.charAt(i));
                }
                if (i < s2.length()) {
                    sb.append(s2.charAt(i));
                }
            },
            StringBuilder::append
    )
    .toString();

这里发生的是,我们循环(使用

IntStream
)两个字符串中最大的一个字符串的所有索引(使用
max(s1.length(), s2.length())
)。

然后我们收集到一个

StringBuilder
中,如果存在则添加
s1
中的字符,然后对
s2
进行同样的操作。

请注意,此代码不使用任何中间子字符串。

但是,我认为 ol' skool for 或 foreach 循环与使用流一样好。

© www.soinside.com 2019 - 2024. All rights reserved.