【问题标题】:Stream.dropWhile() doesn't return correct value in two different valuesStream.dropWhile() 不会以两个不同的值返回正确的值
【发布时间】:2018-10-02 17:39:05
【问题描述】:

我正在尝试学习 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]。 提前致谢。

【问题讨论】:

  • 我的疑问是在第一个条件下它只返回 Hello 并且应该删除左边的两个值。不是吗?

标签: java java-stream java-9


【解决方案1】:

Java 9 中引入的dropWhile method 将删除与谓词匹配的最长起始元素集。

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

因为你的条件是该项为空,且第一项不为空,所以什么都没有去掉,留下["Hello", "", "World"]原封不动。

最后,当你用相反的条件调用dropWhile时,不为空,前3项匹配并被删除,留下["", "e", "f"],这是剩余的项。

这是预期的行为。

【讨论】:

  • 我的疑问是在第一个条件下它只返回 Hello 并且应该删除左边的两个值。不是吗?
  • @HarshKumrawat 不应删除任何内容,因为“与给定谓词匹配的元素的最长前缀”为空。
【解决方案2】:

您的第一个条件是删除项目,直到找到一个非空项目第二个条件说删除项目,直到找到一个空项目。添加一个“!”到你的第一个条件来得到你的预测结果。

【讨论】:

  • 我的疑问是在第一个条件下它只返回 Hello 并且应该删除左边的两个值。不是吗?
  • 只要提供的条件为真,'dropWhile' 就会运行。当条件为假时停止。在第一个循环中,条件从一开始就为假。在第二个循环中,流的 2 个元素都是如此。
  • @HarshKumrawat 他的意思是,当你想要!a.isEmpty() 时,你可以输入a.isEmpty()。这就是为什么输出不是你所期望的。
【解决方案3】:

dropWhile 的 Javadoc 声明:

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

在第一个sn-p中,Stream的第一个元素不满足a -&gt; a.isEmpty(),所以没有元素被丢弃。

在第二个sn-p中,Stream中的前3个元素满足d -&gt; !d.isEmpty(),所以这3个元素被丢弃,留下""、"e"和"f"。

【讨论】:

  • 我的疑问是在第一个条件下它只返回 Hello 并且应该删除左边的两个值。不是吗?
  • @HarshKumrawat 不应删除任何内容,因为“与给定谓词匹配的元素的最长前缀”为空。
【解决方案4】:

为了更好的理解算法,可以尝试换一个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);
}

【讨论】:

  • 由于我正在学习流功能,所以我只想使用流方法。感谢您的回答
  • 这只是换个角度的看法:) ...继续学习!
猜你喜欢
  • 1970-01-01
  • 2016-10-09
  • 2021-10-26
  • 2015-10-13
  • 2014-12-06
  • 2021-02-01
  • 2017-08-21
  • 2021-10-27
  • 2021-02-10
相关资源
最近更新 更多