Java 11 Stream过滤字符串数组指定元素未生效问题排查
问题所在
你的过滤谓词语义和预期完全相反,先拆解你写的条件:
Predicate.not(String::isEmpty).or(entry -> entry.equals("Name"))
这个条件的实际保留规则是:元素满足「非空字符串」、「等于"Name"」两个条件任意一个,就会被留在流中。
逐一代入你的测试元素验证:
- 元素
"Name":本身是非空字符串,直接满足第一个判断条件,不管or后面的逻辑是什么,整个谓词返回true,因此被保留 - 元素
"":不满足「非空」,也不满足「等于"Name"」,谓词返回false,被过滤 - 元素
"First"、"Last":都是非空字符串,满足第一个条件,被保留
最终运行结果是["Name", "First", "Last"],只过滤了空字符串,完全没移除"Name",和预期不符。核心错误有两个:
- 逻辑连接符用错:你需要同时满足两个排除规则,应该用
and而不是or - 第二个判断条件没取反:你要排除等于"Name"的元素,对应的保留条件应该是「不等于"Name"」,而不是「等于"Name"」
修正代码
写法1:拆分保留条件,用and连接
保留的元素需要同时满足「非空」、「不等于"Name"」两个要求:
Arrays.asList(myStringArray).stream() .filter(Predicate.not(String::isEmpty) .and(Predicate.not("Name"::equals))) .collect(Collectors.toList());
写法2:整合排除规则后整体取反(可读性更高)
先定义「要被过滤的元素规则:是空字符串 或者 等于"Name"」,再整体取反作为保留规则,注意要显式声明第一个谓词的类型帮编译器做类型推断:
Arrays.asList(myStringArray).stream() .filter(Predicate.not( ((Predicate<String>) String::isEmpty).or("Name"::equals) )) .collect(Collectors.toList());
两种写法运行你给出的测试数组,最终返回结果都是["First", "Last"],符合过滤预期。
内容的提问来源于stack exchange,提问作者Sangli
相关产品推荐
相关产品推荐

