Stream.dropWhile() 没有以两个不同的值返回正确的值

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

我正在尝试学习 Java-9 中的新功能,我开始了解 Stream 的 dropWhile 方法,但它在两种不同的场景中返回不同的值。 这是我的代码

package src.module;

import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.List;

public class Test {

    public static void main(String[] args) {

        String s[] = new String[3];
        s[0] = "Hello";
        s[1] = "";
        s[2] = "World";
        List<String> value = Stream.of(s).dropWhile(a -> a.isEmpty()).collect(Collectors.toList());

        System.out.println(value);

        List<String> values = Stream.of("a", "b", "c", "", "e", "f").dropWhile(d -> !d.isEmpty())
                .collect(Collectors.toList());
        System.out.println(values);

    }
}

这是我得到的答案

[Hello, , World]
[, e, f]

我认为在第一个条件下它应该打印 [,World]。 预先感谢。

java java-stream java-9
5个回答
3
投票

Java 9 中引入的

dropWhile
方法 将删除与谓词匹配的最长起始元素集。

如果此流是有序的,则在删除与给定谓词匹配的元素的最长前缀后,返回由该流的剩余元素组成的流。

因为你的条件是该项目为空,并且第一个项目不为空,所以没有删除任何内容,保持

["Hello", "", "World"]
完好无损。

最后,当您以相反的条件调用

dropWhile
时,不为空,前 3 项匹配并被删除,留下
["", "e", "f"]
,即剩余的项目。

这是预期的行为。


3
投票

您的第一个条件是删除项目,直到找到非空项目为止。第二个条件是删除项目,直到找到空项目为止。添加一个“!”达到您的第一个条件以获得预测结果。


2
投票

dropWhile 的 Javadoc 指出:

如果此流是有序的,则在删除与给定谓词匹配的元素的最长前缀后,返回由该流的剩余元素组成的流。

在第一个片段中,

Stream
的第一个元素不满足
a -> a.isEmpty()
,因此没有元素被删除。

在第二个片段中,

Stream
中的前3个元素满足
d -> !d.isEmpty()
,因此这3个元素被删除,留下
""
"e"
"f"


2
投票

为了更好的理解算法,可以尝试更换一个

Stream
版本:

List<String> value = Stream.of(s).dropWhile(String::isEmpty).collect(Collectors.toList());

带有经典的

for
循环:

List<String> value = new ArrayList<>();
boolean dropping = true;

for (int i = 0; i < s.length; i++) {
    String str = s[i];
    if (dropping) {
        if (str.isEmpty()) {
            continue;
        }
        dropping = false;
    }
    value.add(str);
}

0
投票

我花了一些时间,才成功地将我头脑中的错误逻辑转变为正确的逻辑。一开始我得到了与 Harsh Kumrawat 相同的结果。

以下两个答案对我帮助最大:

1号

只要提供的条件为真,“dropWhile”就会运行。当条件为假时,它会停止。在第一个循环中,条件从一开始就是假的。在第二个循环中,流的 2 个元素为真。 – x 银子 2018 年 10 月 2 日 17:52

2号

为了更好地理解算法,可以尝试更换一个Stream版本:

 List<String> value = Stream.of(s).dropWhile(String::isEmpty).collect(Collectors.toList());

    with a classic for loop:

    List<String> value = new ArrayList<>();
    boolean dropping = true;

    for (int i = 0; i < s.length; i++) {
    String str = s[i];
    if (dropping) {
        if (str.isEmpty()) {
            continue;
        }
        dropping = false;
    }
    value.add(str);
    }

亚历山大·皮罗霍夫 2018 年 10 月 2 日 17:50

平安归来

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