【问题标题】:Java Arraylist of objects Contains/equalsJava Arraylist of objects 包含/等于
【发布时间】:2013-03-28 17:03:22
【问题描述】:

我查看了很多地方,大多数 arraylist 示例都使用“String”作为元素,但是很难找到使用对象的地方。

假设我正在处理一个图书收藏,并且我有一个作者对象:

class Author {
  String name;
  <other data>;
  int bookCount;

  public Author(String n) {
     name = n;
  }

  public boolean equals(Author other) {
     if (other.name.equals(name)) { return true;}
     return false;
  }
}

所以我创建了一个实例化为 arrayList 的作者列表:

Arraylist<Author> writers;

所以我想知道作者是否存在,如果不存在则创建一个新条目,如果存在则增加 bookCount。我可以在 Author 中的名称上写一个 equals 方法(如上所示),然后执行以下操作:

bookAuthor = "James Gosling"; // normally an input
Author current = new Author(bookAuthor);
if (!writers.contains(current)) {
    writers.add(current);
} else {
    writers.get(writers.indexOf(current)).bookCount++;
}

我相信这会起作用,我发现创建大量对象只是为了在比较之后将它们丢弃是令人反感的,但我遇到的问题是 Author 的普通构造函数不是那么简单,并且涉及数据库查找(如此昂贵)。

这意味着在这种情况下仍然可以使用仅名称构造函数,但是我需要构造两次 Author。我能想到的唯一其他方法是创建一个继承自 ArrayList 并覆盖包含和 indexOf 的新类。这似乎有很多开销,然后我是否还需要在新类中覆盖 equals 或 hashCode 或其他内容?

我是否遗漏了一些东西,是否有某种方法可以提供内联函数或使使用对象容器更容易的方法? 我希望有人可以这样做:

Arraylist<Author> {equals(String x) { if (x = this.name) { return true;} return false; } writers;

if (!writers.contains(bookAuthor)) {
    writers.add(new Author(bookAuthor,dbconn);
} else {
    writers.get(writers.indexOf(bookAuthor)).bookCount++;
}

当然,contains 和 indexOf 没有 String 签名,并且内联的工作量几乎与创建新类的工作量相同。

【问题讨论】:

    标签: java object arraylist containers


    【解决方案1】:

    要解决这个问题,怎么样:

    class Author {
      String name;
      <other data>;
      int bookCount;
    
      public Author(String n) {
         name = n;
      }
    
      @Override
      public boolean equals(Object o) {
         if (this == o) return true;
         if (o == null) return false;
         if (this.getClass() != o.getClass()) return false;
         Author other = (Author) o;
         return other.name.equals(name);
      }
    }
    
    

    将equals 方法的签名更改为Object 类而不是Author,以便Arraylist.contains 方法能够使用它。但是你将不得不强制转换对象以进行必要的比较。

    【讨论】:

      【解决方案2】:

      前段时间我也有过类似的情况,遇到过这样的问题:

      1. 为每个作者分配一个 ID(或任何唯一标识符)。 毕竟按名字搜索很费时间
      2. 将所有数据加载到 HashMap&lt;Long, Author&gt; 中:因为检查 HashMap 和其中的所有 Authors 比每次检查数据库要快。
      3. 在 O(1) 中,您可以通过 hashMap.get(ID) 访问您喜欢的 Author 对象

      【讨论】:

      • 将数据放入 (Hash)Map 会丢失 List 的顺序,但否则这是可行的。如果访问是 O(1),那么键是 Long 还是 String 真的很重要吗?
      • 每件事都有自己的优点和缺点。不,使用Long 或String 作为地图的键没有区别。
      【解决方案3】:

      如果您使用的是真实世界的数据,那么名称是一个糟糕的选择。你认为有多少 John Smiths 会写书?

      您需要一个唯一的标识符,自然数据不会削减它,因此人工 id 字段是最佳选择。

      接下来,您应该覆盖 equals() 以使用 id。 hashCode() 应该基于 equals() 使用的相同字段,因此也相应地覆盖它。

      接下来,使用集合,而不是列表 - 集合保持其元素的不相等性。无需检查!

      【讨论】:

      • 谢谢,但在我的藏书(超过 3000 本书)中,我没有重复作者。虽然这是查找的问题。至于 set vs list,我仍然需要知道它是否存在,看看我是否需要添加或更改数据,所以我认为这不相关。
      【解决方案4】:

      Mybe,你可以使用Map&lt;String,Author&gt; 作为名称->作者映射,这样就可以解决了

      【讨论】:

      • 您是建议并行 Map 存储还是替换列表?如果是后者,据我所知,我只能为作者提取一个 Collection 对象。
      猜你喜欢
      • 1970-01-01
      • 2015-02-13
      • 1970-01-01
      • 2014-09-16
      • 2016-09-22
      • 2016-11-27
      • 2014-07-21
      • 2023-04-05
      • 2013-05-06
      相关资源
      最近更新 更多