"contains()" 方法如何真正作用于 List<string>?

How "contains()" method really work on List<string>?

我正在尝试检查两个列表是否包含相同的值,但我无法弄清楚为什么这个特定值会触发我的 FileException

private static void checkFileHeaders(List<ColumnDefinition> columnsDefinitions, ArrayList<String> columnsName) throws FileException {
    for (ColumnDefinition cd : columnsDefinitions) {
        if(!columnsName.contains(cd.getFieldNameInFile())) {
            throw new FileException("Parameter "+cd.getFieldNameInFile() +" missing ");
        }
    }
}

正如我们在调试器中看到的那样,我的值存在于列表中,它是否与编码有关?它适用于其他值,但不适用于这个特定值。

我知道 contains() 的工作方式与 equals() 类似,所以这里有什么问题

如果我看单个字符:

cd.getFieldNameInFile() : [90, 66, 75, 80, 70, 45, 66, 85, 75, 82, 83]

列名[0] : [-1, -2, 90, 0, 66, 0, 75, 0, 80, 0, 70, 0, 45, 0, 66, 0, 85, 0, 75 , 0, 82, 0, 83, 0]

如何解决这个差异,原因是什么?

它检查每个元素,如果它是 equal() 到您正在测试的元素。意思是,如果两个元素通过 equals() 方法测试,contains()方法将为他们 return true,如果 equals() 方法 return 为 false,那么 contains() 方法也会如此。

来自 Java 文档:

boolean contains(Object o)

Returns true if this list contains the specified element. More formally, returns true if and only if this list contains at least one element e such that (o==null ? e==null : o.equals(e)).

文档Link

https://docs.oracle.com/javase/8/docs/api/java/util/List.html#contains-java.lang.Object-

显然 getFieldNameInFile 不是字符串。所以应该拿 toString,

private static void checkFileHeaders(List<ColumnDefinition> columnsDefinitions,
        List<String> columnsName) throws FileException {
    for (ColumnDefinition cd : columnsDefinitions) {
        if(!columnsName.contains(cd.getFieldNameInFile().toString()) {
            throw new FileException("Parameter "+cd.getFieldNameInFile() +" missing ");
        }
    }
}

使用流:

private static void checkFileHeaders(List<ColumnDefinition> columnsDefinitions,
        Set<String> columnsName) throws FileException {
    if (columnsDefinitions.streams
            .map(ColumnDefinition::getFieldNameInFile)
            .map(Object::toString)
            .anyMatch(nm -> !columnsName.contains(nm)) {
        throw new FileException("Parameter " + cd.getFieldNameInFile() + " missing ");
    }
}

此外ArrayList它太具体了,使用一个接口,List因为这个方法可以用于任何类型的列表实现。

Set<String> 对于 contains 来说会快得多,例如 HashSet<>

我们忽略考虑的是,即使为 class 定义了 equals() 方法,hashCode() 方法仍然需要关心(即使在这里你假设比较字符串可能不是?)。

为什么?

contains 依赖于 equals 并且 equals 与 hashCode 一起工作以判断我们是否在此处谈论引用术语中的同一对象。

根据 equals-hashCode 合同恢复 contains() 工作 More documentation