【问题标题】:Java ArrayList.contains() & add() methodJava ArrayList.contains() 和 add() 方法
【发布时间】:2014-05-15 08:06:21
【问题描述】:

所以我在向 ArrayList 添加元素时遇到了这个问题

我有一个类 Media 有 3 个字段,另一个类 Mediatheque 有 1 个字段(这是一个 ArrayList)。

假设我有:

  • Mediatheque media = new Mediatheque

  • Media 类中的一个equals(Media m) 方法

我需要写一个方法add(Media m)

  • 如果media.contenu确实包含一个元素equals到我想添加的Media m,我不能添加它并增加media.contenu中包含的元素的nbEx字段

-否则我可以使用ArrayList提供的add方法添加它(这似乎不太难)

所以我尝试编写一个contains(Media) 方法,它使用我为Media 类编写的equals(Media m) 方法,然后在add 方法中使用contains 方法。

我的问题是我应该如何编写add 方法?

我必须用ArrayList 写这个,这是一个学校作业 抱歉,代码太长,英语不好,我完全是菜鸟。

这是我的Media 班级:

package Ex1;

public class Media {
    private final String support; // Format: Book, CD, DVD,etc...
    private final String titre; // Title
    private int nbEx; // Number of copy

    public Media(String titre, String support){
        this.titre = titre;
        this.support = support;
        this.nbEx = 1;
    }

    public Media (){
        titre = "";
        support = "";
        nbEx = 0;
    }

    public boolean equals(Media m){
        boolean equality = false;
            if (m instanceof Media){
                equality = (this.titre.equals(m.titre) && this.support.equals(m.support));
            }
        return equality;
    }

    public Media(Media m){
        this.titre = m.titre;
        this.support = m.support;
    }
}

这是我的Mediatheque 课程:

import java.util.ArrayList;
import static java.lang.System.out;

public class Mediatheque {
    ArrayList<Media> contenu;

    public Mediatheque(){
        this.contenu = new ArrayList<Media>();
    }

    public Mediatheque(Mediatheque m){
        this.contenu = m.contenu;
    }

    public boolean contains(Media m){
        int i = 0;
        boolean contain = this.contenu.get(i).equals(m);
        for(i = 0; i<this.contenu.size(); i++){
            if(contain)
                break;
        }
        return contain;
    }

    public int indexOf(Media m){
        boolean retVal = this.contenu.get(i).equals(m);
        for(Media i : contenu){
            if(contain)
                break;
        }
        return i;
    }

    public void add(Media m){
        if(this.contains(m)){
            this.contenu.get(this.contenu.indexOf(m)).setNbEx(this.contenu.get(this.contenu.indexOf(m)).getNbEx()+m.getNbEx());
        }else{
            this.contenu.add(m);
        }
    }

我的问题是我应该如何编写add 方法?

对不起,代码太长,英语不好,我是一个完全的菜鸟。

谢谢!

【问题讨论】:

  • 这里的限制到底是什么? Media 类中的标题,还是 supportnbEx 也算?
  • 你为什么要为ArrayList#contains重新发明轮子?
  • 既然你已经实现了equals方法,为什么不直接使用ArrayList.contains呢?
  • 我认为你应该修改你的数据模型。将多个副本存储在 Media 对象中没有多大意义(据我所知,Media 的实例是一个项目)。例如使用Map&lt;Media, Integer&gt; 会更清晰(更快)。并且只增加地图中的数字。您正在创建一个类似集合的新数据结构,但您可能应该重用 JDK 提供的内容。
  • 你的 equals 方法应该接受一个对象作为参数

标签: java arrays arraylist add contains


【解决方案1】:

正如@NeplatnyUdaj 在您的问题评论中所述,使用Map 将大大改进您的代码。不要在 Media 对象中记录媒体的数量,而是使用 HashMap&lt;Media, Integer&gt; 以这种方式存储您的数据:

new HashMap<Media, Integer> map = new HashMap<Media,Integer>();

if ( map.containsKey(key) ) {
    map.put(key, (map.get(key) + 1));
} else {
    map.put(key, 1);
}

key 是媒体。 (m 在您的代码中)

【讨论】:

    【解决方案2】:

    我已经稍微重构了你的类。我还实现了一个 add 方法。我假设您想将媒体添加到媒体库(如果它不在列表中)。如果它在列表中,您想将 nbex 添加到列表中的项目所具有的 nbex 中,对吗? 与其他人一样,如果您不需要媒体对象的数字,我建议您使用 HashMap() 进行计数。

    媒体类

    public class Media {
        private final String support; // Format: Book, CD, DVD,etc...    
        private final String titre; // Title    
        private int nbEx; // Number of copy
    
        public Media(String titre, String support){
            this.titre = titre;
            this.support = support;
            this.nbEx = 1;
        }
    
        public Media(Media m){
            this(m.titre, m.support);
        }
    
        public Media (){
            this("", "");
            nbEx = 0;
        }
    
        public boolean equals(Media m){
                if (m instanceof Media){
                    return (this.titre.equals(m.titre) && this.support.equals(m.support));
                }
            return false;
        }
    }
    

    Mediatheque.class

    public class Mediatheque {
        ArrayList<Media> contenu;
    
        public Mediatheque(){
            this.contenu = new ArrayList<Media>();
        }
    
        public Mediatheque(Mediatheque m){
            this.contenu = m.contenu;
        }
    
        public boolean contains(Media m){
            for(Media media: this.contenu) {
                if(media.equals(m) {
                    return true;
                }
            }
            return false;
        }
    
        public int indexOf(Media m){
            if(this.contenu.contains(m) {
                return this.contenu.indexOf(m);
            }
            return -1;
        }
    
        public void add(Media m){
            if(this.contains(m)) {
                Media media = this.contenu.get(this.contenu.indexOf(m));    
                media.setNbex(media.getNbex() + m.getNbex());
            } else {
                this.contenu.add(m);
            }
        }
    }
    

    希望这会有所帮助。

    【讨论】:

    • 谢谢您,先生。但是你写的 contains 方法好像不起作用,我不知道为什么但我感觉它总是返回 false。
    • 是的,可能是因为 equals 方法的签名错误:它是 public boolean (Media media) {...} 而不是 public boolean(Object object) {...}。所以它没有覆盖 Object 继承的 equals 方法,因此从未使用过。感谢您的评论。
    【解决方案3】:

    当一个覆盖equals() 方法时,一个也应该覆盖hashCode() 方法。 equals() 方法采用 Object 参数。以下是您的 Media 类的外观:

    // Media.java
    public class Media
    {
      private final String support;
      private final String title;
    
      public Media(String title, String support)
      {
        this.title = title;
        this.support = support;
      }
    
      public Media(Media media)
      {
        this(media.title, media.support);
      }
    
      @Override
      public int hashCode()
      {
        return 31 * title.hashCode() + support.hashCode();
      }
    
      @Override
      public boolean equals(Object object)
      {
        if (object instanceof Media)
        {
          Media media = (Media) object;
    
          return media.title.equals(title) &&
                 media.support.equals(support);
        }
    
        return false;
      }
    }
    

    然后使用 HashMap 将媒体与其副本数进行映射。这是如何完成的:

    // MediaMap.java
    import java.util.HashMap;
    import java.util.Map;
    
    public class MediaMap
    {
      // Media to its Number of Copies mapping.
      private Map<Media, Integer> mediaMap;
    
      public MediaMap()
      {
        mediaMap = new HashMap<>();
      }
    
      public void add(Media media)
      {
        mediaMap.put(media, mediaMap.getOrDefault(media, 0) + 1);
      }
    
      public void removeOneMedia(Media media)
      {
        if (mediaMap.containsKey(media))
        {
          mediaMap.put(media, mediaMap.get(media) - 1);
        }
      }
    
      // And so on...
    }
    

    如果不覆盖 Media 类中的 hashCode() 方法,基于散列的集合将无法按预期工作。

    您还可以查看MultiSet 数据结构,并改用它。

    如果您要使用ArrayList,那么它是如何完成的:

    // Media.java
    public class Media
    {
      private final String support;
      private final String title;
      private int numberOfCopies;
    
      public Media(Media media)
      {
        this(media.title, media.support, media.numberOfCopies);
      }
    
      public Media(String title, String support, int numberOfCopies)
      {
        this.title = title;
        this.support = support;
        this.numberOfCopies = numberOfCopies;
      }
    
      @Override
      public int hashCode()
      {
        return 31 * title.hashCode() + support.hashCode();
      }
    
      @Override
      public boolean equals(Object object)
      {
        if (object instanceof Media)
        {
          Media media = (Media) object;
    
          return media.title.equals(title) &&
                 media.support.equals(support);
        }
    
        return false;
      }
    
      public int getNumberOfCopies()
      {
        return numberOfCopies;
      }
    
      public void setNumberOfCopies(int numberOfCopies)
      {
        this.numberOfCopies = numberOfCopies;
      }
    }
    

    这是一个使用ArrayListMediaList 类:

    // MediaList.java
    import java.util.ArrayList;
    
    public class MediaList
    {
      private ArrayList<Media> mediaList;
    
      public MediaList()
      {
        mediaList = new ArrayList<>();
      }
    
      public void add(Media media)
      {
        set(media, +1);
      }
    
      public void remove(Media media)
      {
        set(media, -1);
      }
    
      private void set(Media media, int change)
      {
        if (change == 0)
        {
          return;
        }
    
        int indexOfMedia = mediaList.indexOf(media);
    
        if (indexOfMedia != -1)
        {
          Media m = mediaList.get(indexOfMedia);
          m.setNumberOfCopies(m.getNumberOfCopies() + change);
    
          if (change < 0 && m.getNumberOfCopies() <= 0)
          {
            mediaList.remove(media);
          }
        }
        else if (change > 0)
        {
          mediaList.add(media);
        }
      }
    
      // And so on...
    }
    

    【讨论】:

    • 谢谢您,先生,您的媒体课确实看起来更好了。但我应该使用 ArrayList 因为……嗯,学校很烂。
    • @Heuksal:我已经更新了答案。您可以使用ArrayList 查看特定代码是如何编写的。
    • 如您所示,只需覆盖equals 方法即可解决问题。感谢您的关注,先生。
    • @Heuksal:酷。 :) 你可以通过接受任何答案来结束这个问题。
    猜你喜欢
    • 2013-04-07
    • 1970-01-01
    • 1970-01-01
    • 2013-08-28
    • 1970-01-01
    • 1970-01-01
    • 2017-03-20
    • 2015-08-08
    • 2012-09-18
    相关资源
    最近更新 更多