【问题标题】: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 是避免重复的更好方法。

标签: java object arraylist equals contains


【解决方案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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-16
      • 1970-01-01
      • 2020-07-18
      • 1970-01-01
      • 2012-08-28
      • 2018-07-16
      • 1970-01-01
      相关资源
      最近更新 更多