【问题标题】:contains with ObservableList () returns always false包含与 ObservableList() 总是返回 false
【发布时间】:2021-09-23 20:37:23
【问题描述】:

我在我的 JavaFX 代码中使用 ObservableList,我正在尝试测试该列表中是否存在一个对象,但即使对于其中已经存在的对象,它也总是返回 false。 这是我的代码:

private ObservableList<OMission> UserMission = FXCollections.observableArrayList();    

OMission OM1 = new OMission(1,"user_firstname","user_lastname");


UserMission.add(OM1);



if(UserMission.contains(new OMission(1,"user_firstname","user_lastname")){

System.out.println("true");}

else {

System.out.println("false");

}

我期待得到“真实”,但我总是得到虚假

发生了什么?

【问题讨论】:

  • 发布minimal reproducible example(并使用正确的命名约定)。可能OMission.equals(…) 没有返回正确的结果。我假设System.out.println(userMission.contains(om1)); 打印true,正如预期的那样。
  • .. 请遵守 java 命名约定

标签: java list object javafx observablelist


【解决方案1】:

您可能忽略了为equalshashCode 实现关键的Object 覆盖。

此问题并非特定于 OpenJFX 类 ObservableList。任何执行比较的集合(列表、集合、映射等)都将取决于您为至少equals 和可能的hashCode 编写适当的覆盖。 (提示:总是覆盖两者或都不覆盖,永远不要单独覆盖。)

以下是使用修改后的代码的示例代码。顺便说一句,你错过了一个右括号。此外,如果您遵循 Java 命名约定,生活会更轻松。

为简洁起见,我们使用 Java 16+ 中的新 records 功能。记录是编写类的一种更简洁的方式,其主要目的是透明且不可变地传递数据。您只需要声明每个成员字段的类型和名称。编译器隐式创建构造函数、getter、equals & hashCodetoString。最后三个方法默认检查每个成员字段的值。

为简单起见,我们在本地声明了record。您也可以将其声明为嵌套或分离。

package work.basil.example;

import javafx.collections.*;

public class App {
    public static void main ( String[] args ) {
        System.out.println ( "Hello World!" );
        App app = new App ();
        app.demo ();
    }

    private void demo () {
        record Person( int id , String firstName , String lastName ) { }

        ObservableList < Person > UserMission = FXCollections.observableArrayList ();
        Person p1 = new Person ( 1 , "Alice" , "Anderson" );
        UserMission.add ( p1 );
        if ( UserMission.contains ( new Person ( 1, "Alice" , "Anderson" ) ) ) {
            System.out.println ( "true" );
        } else {
            System.out.println ( "false" );
        }
    }
}

运行时。

世界你好!

是的

如果使用 Java 的早期版本,或者如果记录不适合您的情况,请编写类似于以下内容的类。注意方法equals & hashCode

package work.basil.example;

import java.util.Objects;

public final class Person {
    private final int id;
    private final String firstName;
    private final String lastName;

    public Person ( int id , String firstName , String lastName ) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public int id () { return id; }

    public String firstName () { return firstName; }

    public String lastName () { return lastName; }

    @Override
    public boolean equals ( Object obj ) {
        if ( obj == this ) return true;
        if ( obj == null || obj.getClass () != this.getClass () ) return false;
        var that = ( Person ) obj;
        return this.id == that.id &&
                Objects.equals ( this.firstName , that.firstName ) &&
                Objects.equals ( this.lastName , that.lastName );
    }

    @Override
    public int hashCode () {
        return Objects.hash ( id , firstName , lastName );
    }

    @Override
    public String toString () {
        return "Person[" +
                "id=" + id + ", " +
                "firstName=" + firstName + ", " +
                "lastName=" + lastName + ']';
    }
}

覆盖equals/hashCode的问题已经被讨论过很多次了。 Search to learn more.

【讨论】:

    【解决方案2】:

    Basil 在我写这篇文章时同时更新了他的答案,包括一些额外的信息。因此,此答案中重复了一些信息。请原谅这里的任何重复。我暂时保留这个答案。


    为了补充 Basil 的回答,一些不同的解决方案是:

    1. 编写 equals 和 hashcode 的自定义实现。

    对于 OMission,实现 equals(Object obj)(最好也实现 hashCode())。

    您最终会得到类似 Basil 示例答案中的代码。

    您可以自己从头开始编写这些方法,但是我不建议这样做。手工编写这些函数时,很容易犯不必要的愚蠢错误。

    1. 使用 IDE 自动生成 equals 和 hashcode 的实现。

    大多数 IDE 都有一个菜单项或快捷方式来自动生成这些方法(请参阅 how to do this in Idea)。这就是我通常生成这些函数的方式。如果我在类中添加或删除一个字段,那么我会删除以前自动生成的函数并自动生成新的函数。

    1. 使用第 3 方库生成 equals 和哈希码。

    第三方库,例如Lombok,可用于自动生成方法。 Lombok 将通过annotations 执行此操作,例如只需将注释 @EqualsAndHashcode 添加到您的类定义中即可。

    1. 使 OMission 成为记录而不是类。

    如果数据可以表示为不可变的record 而不是类是合适的,那么这是推荐的方法。它不适用于所有数据类型。

    默认情况下,记录实现适当的equals和hashcode方法。

    record OMission(
        int missionNum, 
        String firstname, 
        String lastname
    ) {}
    

    【讨论】:

      猜你喜欢
      • 2018-12-02
      • 2019-05-05
      • 2017-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-20
      相关资源
      最近更新 更多