如果用户已经提供了对象,如何停止将用户提供的对象添加到数组列表中? [关闭]

Posted

技术标签:

【中文标题】如果用户已经提供了对象,如何停止将用户提供的对象添加到数组列表中? [关闭]【英文标题】:How to stop adding objects given by the user to an arraylist if they already gave it? [closed] 【发布时间】:2021-09-08 10:26:17 【问题描述】:

这是课

public class Book 
    private String name;
    private int publicationYear;
    public Book(String name, int publicationYear) 
        this.name = name;
        this.publicationYear = publicationYear;
    
    public boolean equals(Book compared) 
        if (this == compared) 
            return true;
        
        if (!(compared instanceof Book)) 
            return false;
        
        Book comparedBook = (Book) compared;
        if (this.name.equals(comparedBook.name)
                && this.publicationYear == comparedBook.publicationYear) 
            return true;
        
        return false;
    

我尝试在主程序中这样做

while (true) 
    System.out.println("Name (empty will stop):");
    String name = scanner.nextLine();
    if (name.isEmpty()) 
        break;
    
    System.out.println("Publication year:");
    int publicationYear = Integer.valueOf(scanner.nextLine());
    Book book = new Book(name, publicationYear);
    if (!(books.contains(book))) 
        books.add(book);
    

因此,如果用户继续提供具有相同名称和年份的书,程序仍会将它们添加到列表中

【问题讨论】:

有什么问题? 列表确实是错误的工作工具; Set 是避免重复的更好方法。 【参考方案1】:

Answer by Elliott Frisch 是正确而明智的。

或者,在 Java 16+ 中,您可以通过让 Java 处理 equals 的实现来避免错误编写 equals 方法的问题。

record

Java 16 带来了records 功能。记录是编写类的一种简短方式,其主要目的是透明且不可变地传递数据。您只需声明每个成员字段的类型和名称。编译器隐式创建构造函数、getter、equals & hashCodetoString

顺便说一句,Java 提供了一个类来表示年份:java.time.Year

public record Book ( String title , Year published )  

equals 等隐式方法被实现以考虑每个成员字段。

new Book( "Free To Choose" , Year.of( 1990 ) )
.equals( 
    new Book( "The Foundation Trilogy" , Year.of( 1974 ) ) 
)

您可以在本地、嵌套或单独定义记录。 Java 16 及更高版本中的枚举和接口也是如此。

Set

要在自动消除重复项的同时收集对象,请使用Set 实现。

Set< Book > books = new HashSet<>() ;
books.add( new Book( "Free To Choose" , Year.of( 1990 ) ) ) ;
books.add( new Book( "Free To Choose" , Year.of( 1990 ) ) ) ;  // Duplicate! Not added, because a set does not allow duplicates.
books.add( new Book( "The Foundation Trilogy" , Year.of( 1974 ) ) ) ;

Interrogate for the size。您会找到 2 号而不是 3 号。

【讨论】:

【参考方案2】:

您不能更改Object.equals(Object) 的签名。

您应该使用@Override 注释来捕获此类错误。请参阅 Oracle 的 tutorial。

@Override
public boolean equals(Object compared) 
    if (this == compared) 
        return true;
    
    if (!(compared instanceof Book)) 
        return false;
    
    Book comparedBook = (Book) compared;
    if (this.name.equals(comparedBook.name)
            && this.publicationYear == comparedBook.publicationYear) 
        return true;
    
    return false;

【讨论】:

以上是关于如果用户已经提供了对象,如何停止将用户提供的对象添加到数组列表中? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

对象导论系列---每个对象都提供服务

Django的认证系统

asp中如何检测用户名已经存在?

如何在 GraphQL 突变/解析器中为每个用户创建和停止唯一的计时器

如何使 Vert.x JWTAuthHandler 只注入用户对象而不拒绝未经授权的请求?

如何使用JDBC实现数据访问对象层(DAO)