contains with ObservableList () returns 始终为 false
contains with ObservableList () returns always false
我在我的 JavaFX 代码中使用 ObservableList,我试图测试该列表中是否存在一个对象,但它总是 returns 错误,即使对于已经存在于其中的对象也是如此。
这是我的代码:
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");
}
我期待得到“真”,但我总是得到假
发生了什么事?
您可能忽略了为 equals
和 hashCode
实施关键的 Object
覆盖。
此问题不是 OpenJFX class ObservableList
所特有的。执行比较的任何集合(列表、集合、映射等)都将取决于您是否为至少 equals
和可能 hashCode
编写适当的覆盖。 (提示:总是覆盖两者或两者都不覆盖,永远不要单独覆盖一个。)
下面是使用您的代码的修改版本的示例代码。顺便说一下,你少了一个 right-paren。此外,如果您遵循 Java 命名约定,生活会更轻松。
为简洁起见,我们使用 Java 16+ 中的新 records 功能。记录是编写 class 的一种更简洁的方式,其主要目的是透明且不可变地传递数据。您只需要声明每个成员字段的类型和名称。编译器隐式创建构造函数、getter、equals
& hashCode
和 toString
。最后三种方法默认检查每个成员字段的值。
为简单起见,我们在本地声明了 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" );
}
}
}
当运行.
Hello World!
true
如果使用 Java 的早期版本,或者如果记录不适合您的情况,请编写类似于以下内容的 class。注意方法 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.
Basil 在我撰写本文时同时更新了他的答案以包含一些附加信息。因此,此答案中有一些信息是重复的。请原谅这里的任何重复。我暂时保留这个答案。
为了补充 Basil 的回答,一些不同的解决方案是:
- 编写 equals 和 hashcode 的自定义实现。
对于 OMission,实施 equals(Object obj)
(最好也实施 hashCode()
)。
您最终会得到类似于 Basil 示例答案中的代码。
您可以自己从头开始编写这些方法,但是,我不推荐这样做。手动编写这些函数时很容易犯不必要的愚蠢错误。
- 使用 IDE 自动生成 equals 和 hashcode 的实现。
大多数 IDE 都有一个菜单项或快捷方式来自动生成这些方法(请参阅 how to do this in Idea)。这就是我通常生成这些函数的方式。如果我向 class 添加或删除一个字段,那么我会删除以前自动生成的函数并自动生成新的。
- 使用第 3 方库生成等号和哈希码。
第三方库,例如Lombok, can be used to autogenerate the methods. Lombok will do this via annotations,例如只需将注释 @EqualsAndHashcode
添加到您的 class 定义中即可。
- 将 OMission 设为记录而不是 class。
如果可以将数据表示为不可变 record 而不是 class 是合适的,那么这是推荐的方法。它不适用于所有数据类型。
默认情况下,记录实现适当的 equals 和 hashcode 方法。
record OMission(
int missionNum,
String firstname,
String lastname
) {}
我在我的 JavaFX 代码中使用 ObservableList,我试图测试该列表中是否存在一个对象,但它总是 returns 错误,即使对于已经存在于其中的对象也是如此。 这是我的代码:
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");
}
我期待得到“真”,但我总是得到假
发生了什么事?
您可能忽略了为 equals
和 hashCode
实施关键的 Object
覆盖。
此问题不是 OpenJFX class ObservableList
所特有的。执行比较的任何集合(列表、集合、映射等)都将取决于您是否为至少 equals
和可能 hashCode
编写适当的覆盖。 (提示:总是覆盖两者或两者都不覆盖,永远不要单独覆盖一个。)
下面是使用您的代码的修改版本的示例代码。顺便说一下,你少了一个 right-paren。此外,如果您遵循 Java 命名约定,生活会更轻松。
为简洁起见,我们使用 Java 16+ 中的新 records 功能。记录是编写 class 的一种更简洁的方式,其主要目的是透明且不可变地传递数据。您只需要声明每个成员字段的类型和名称。编译器隐式创建构造函数、getter、equals
& hashCode
和 toString
。最后三种方法默认检查每个成员字段的值。
为简单起见,我们在本地声明了 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" );
}
}
}
当运行.
Hello World!
true
如果使用 Java 的早期版本,或者如果记录不适合您的情况,请编写类似于以下内容的 class。注意方法 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.
Basil 在我撰写本文时同时更新了他的答案以包含一些附加信息。因此,此答案中有一些信息是重复的。请原谅这里的任何重复。我暂时保留这个答案。
为了补充 Basil 的回答,一些不同的解决方案是:
- 编写 equals 和 hashcode 的自定义实现。
对于 OMission,实施 equals(Object obj)
(最好也实施 hashCode()
)。
您最终会得到类似于 Basil 示例答案中的代码。
您可以自己从头开始编写这些方法,但是,我不推荐这样做。手动编写这些函数时很容易犯不必要的愚蠢错误。
- 使用 IDE 自动生成 equals 和 hashcode 的实现。
大多数 IDE 都有一个菜单项或快捷方式来自动生成这些方法(请参阅 how to do this in Idea)。这就是我通常生成这些函数的方式。如果我向 class 添加或删除一个字段,那么我会删除以前自动生成的函数并自动生成新的。
- 使用第 3 方库生成等号和哈希码。
第三方库,例如Lombok, can be used to autogenerate the methods. Lombok will do this via annotations,例如只需将注释 @EqualsAndHashcode
添加到您的 class 定义中即可。
- 将 OMission 设为记录而不是 class。
如果可以将数据表示为不可变 record 而不是 class 是合适的,那么这是推荐的方法。它不适用于所有数据类型。
默认情况下,记录实现适当的 equals 和 hashcode 方法。
record OMission(
int missionNum,
String firstname,
String lastname
) {}