问题描述
我为 Hamcrest 和 Map 编写了这个测试程序,以使用 Hamcrest Matchers。 这个程序使用 Hamcrest 作为独立的(不使用 JUnit)。 为什么没有一个输出为真(匹配)? 如何修改此测试程序,以便匹配 Map 中的键或值(输出为真)?
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.hamcrest.Matchers;
import org.hamcrest.collection.IsMapContaining;
public class TestMap {
public static void main(String[] args) {
Map<String,Integer> map = Stream.of(new Object[][] {
{ "data1",1 },{ "data2",2 },}).collect(Collectors.toMap(data -> (String) data[0],data -> (Integer) data[1]));
for (Map.Entry<String,Integer> entry : map.entrySet()) {
System.out.println("Matchers.hasKey(\"data1\") " + Matchers.hasKey("data1").matches("data1"));
System.out.println("Matchers.hasValue(1) " + Matchers.hasValue(1).matches(1));
System.out.println("IsMapContaining.hasKey(\"data1\") " + IsMapContaining.hasKey("data1").matches("data1"));
System.out.println("IsMapContaining.hasValue(1) " + IsMapContaining.hasValue(1).matches(1));
System.out.println("IsMapContaining.hasEntry(entry.getKey(),entry.getValue()) " + IsMapContaining.hasEntry(entry.getKey(),entry.getValue()));
}
}
}
输出为:
Matchers.hasKey("data1") false
Matchers.hasValue(1) false
IsMapContaining.hasKey("data1") false
IsMapContaining.hasValue(1) false
IsMapContaining.hasEntry(entry.getKey(),entry.getValue()) map containing ["data2"-><2>]
Matchers.hasKey("data1") false
Matchers.hasValue(1) false
IsMapContaining.hasKey("data1") false
IsMapContaining.hasValue(1) false
IsMapContaining.hasEntry(entry.getKey(),entry.getValue()) map containing ["data1"-><1>]
解决方法
我只会解释第一个,其余的你可以自己理解(顺便说一句,这不完全是你的错)。
你认为这里会发生什么:
Matchers.hasKey("data1").matches("data1")
让我们阅读 hasKey
的文档:
当检查的 java.util.Map
包含至少一个等于指定键的键时,为 java.util.Map
的匹配创建匹配器。
现在,让我们阅读 matches
的文档:
这个方法匹配Object,而不是泛型类型T。这是因为Matcher的调用者在运行时不知道类型是什么(因为Java泛型的类型擦除)。 检查正确的类型取决于实现。
理想情况下,您希望 编译器 (javac
) 只允许您在 Map
中指定 matches
(而不是 "data1"
字符串) .毕竟,您确实说过要比较 hasKey
和 Map
,不是吗?但正如文档中所说:“检查正确的类型取决于实现”,javac
不能简单地做到这一点(这是一个限制);你需要自己做。
简单来说,这个 Matchers.hasKey("data1").matches("data1")
甚至不应该编译,但是因为这是 javac
的工作方式(并且因为 hamcrest
像这样设计了他们的代码),这确实可以编译,使用类型错误。
解决方案很简单:
System.out.println("Matchers.hasKey(\"data1\") " + Matchers.hasKey("data1").matches(map));
注意 matches(map)
...