如何在Java 8流中进行条件操作以跳过下一个流操作?

4
在传统方法中,我编写了这个简单的Java for循环。
public String setString(String string) {  
StringBuilder stringBuilder = new StringBuilder();

    // This for loop I want to convert into stream. 
    for (char c : string.toCharArray()) {
       if (Character.isSpaceChar(c))
           stringBuilder.append(c);
       else if (isBangla(c))
           stringBuilder.append(get(c));
    }
    return stringBuilder.toString();
}

String get(int c) {
    return keyMap.getMap((char) c); // Map<Character, String> keyMap
}

boolean isBangla(int codePoint) {
    return ((codePoint >= BANGLA_CHAR_START && codePoint <= BANGLA_CHAR_END) &&
        (codePoint <= BANGLA_NUMBER_START || codePoint >= BANGLA_NUMBER_END)));
}

我尝试过做类似这样的事情。

String str = string.chars()
            .filter(i -> Character.isSpaceChar(i)) // if this is true need to add string 
            .filter(this::isBangla)
            .mapToObj(this::get)
            .collect(Collectors.joining());

我试图做的是,如果第一个筛选器检测到它是一个spaceChar,那么它将不会进行任何进一步的流处理,而是跳转到collect
那么我该如何实现这种if/else情况以跳过下一个流操作呢?提前感谢您的帮助。

1
您无法通过流实现if/else。 - Ihor Dobrovolskyi
@RealSkeptic 是的。如果它是一个 spaceChar,那么我就不需要检查下面的两个操作了。但是因为它是 IntStream,所以我还需要“映射到 obj”。但是正如你在我的 for 循环中看到的那样,这并不是必要的。 - seal
1
问题是为什么你想要这个作为一个流。你的循环已经正确且高效地完成了它。在流中,你可能需要检查它是否为 bangla 两次 - 一次用于过滤,一次用于映射。因此,它的效率较低。 - RealSkeptic
@RealSkeptic,我想知道如何将它转化为流(stream),但是我找不到解决的方法。 - seal
1个回答

9

嗯,你可能可以使用类似这样的东西:

String str = string.chars()
           .filter( ch -> Character.isSpaceChar(ch) || isBangla(ch) )
           .mapToObj( ch -> isBangla(ch) ? get(ch) : Character.toString((char)ch))
           .collect(Collectors.joining());

正如您所看到的,这个流两次检查isBangla。第一次是为了仅在流中留下空格或孟加拉字符,第二次是为了知道要转换哪些字符。
因为流操作是独立的 - 每个流不知道之前的流发生了什么 - 这样的操作在传统循环中编写可能更有效。而且,在流中运行此代码时,您正在创建许多小字符串,其中必须将所有字符转换为字符串,而不仅仅是孟加拉语字符。
重要的是要注意,在这里您并没有“跳过”任何内容。在传统循环中,可以跳过操作。但在流中,跳过元素意味着它们不会出现在最终结果中。在流中,您所做的是保持那些元素不变(或在这种情况下,从char更改为String),而不是跳过。

你能解释一下“创建许多小字符串”的意思吗?从你的最后一段中我理解到,所有的字符都被转换为字符串,但没有添加到最终结果中。 - seal
2
@seal 当你将流转换为对象时,所有字符都变成了字符串对象,然后才被收集起来。String是不可变的,所以临时对象会被复制到最终结果中。因此,当你使用StringBuilder时,没有将其转换为String,而是直接将字符写入StringBuilder,所以没有创建临时对象占用内存,并且也不需要进行垃圾回收。 - RealSkeptic
但是为什么所有字符都变成字符串对象了?难道filter()方法不是只过滤孟加拉字符和空格字符吗? - seal
1
@seal 是的,我主要是在谈论空格字符。在您最初的循环中,它们作为char添加到了StringBuilder中,没有任何字符串。在流中,它们被映射成新的字符串对象,然后收集所有的字符串 - 孟加拉和空格字符串。 - RealSkeptic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接