如何在ArrayList中限制对象数量

3

我正在为下周的面向对象编程考试做一些复习,遇到了一个问题。问题基本上是给出狗和跳蚤之间双向关联的例子。到目前为止,我有一只有跳蚤的狗。我卡在的部分是,“修改狗类,使得狗对象最多只能持有5个跳蚤对象(如果有超过5个跳蚤,则打印“你的狗有太多的跳蚤!”)。这是我的代码:

Dog.java

import java.util.ArrayList;

public class Dog {

    private String name;
    private int age;
    private String address;

    ArrayList<Flea> fleas = new ArrayList<Flea>(); {
        if(fleas.size() > 5) {
             System.out.println("This dog has too many fleas!");
        }
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public void hostFlea(Flea flea) {
        fleas.add(flea);
    }

    public ArrayList<Flea> getDogFlea() {
         return fleas;
    }

    public String toString() {
        return name + " the Dog (aged " + age + ") has fleas. \nThey are: " + fleas + ".";
    }   

}

Flea.java

public class Flea {

    private String name;
    private int age; 

    public Flea (String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return name + " (aged " + age + ")";
    }

}

Test.java

public class Test {

    public static void main(String[] args) {

        Dog dog = new Dog();
            dog.setName("Freddy");
            dog.setAddress("Cork");
            dog.setAge(5);

        Flea flea1 = new Flea("John", 1);
        dog.hostFlea(flea1);

        Flea flea2 = new Flea("Patrick", 3);        
        dog.hostFlea(flea2);

        Flea flea3 = new Flea("Alan", 7);
        dog.hostFlea(flea3);

        Flea flea4 = new Flea("Steven", 2);
        dog.hostFlea(flea4);

        Flea flea5 = new Flea("Charles", 5);
        dog.hostFlea(flea5);

        Flea flea6 = new Flea("Derek", 1);
        dog.hostFlea(flea6);

        Flea flea7 = new Flea("Kevin", 8);
        dog.hostFlea(flea7);

        System.out.println(dog);

    }

}

控制台:

5岁的狗弗雷迪有跳蚤。 它们是:[1岁的约翰,3岁的帕特里克,7岁的艾伦,2岁的史蒂文,5岁的查尔斯,1岁的德里克,8岁的凯文]。


hostFlea 方法的定义是什么? - Nate Barbettini
4个回答

1
在这里添加检查您的条件:
public void hostFlea(Flea flea) {
    if(fleas.size() >= 5) {
        System.out.println("This dog has too many fleas!");
    } else {
        fleas.add(flea);
    }
}

你不应该在定义列表变量时添加实例初始化块,而是像你所做的那样。


谢谢,我把它放错地方了,现在懂了!我还在 IF 语句中加入了 "System.exit(0);",这样信息就不会出现了,除非跳蚤数量少于5只。再次感谢。 - Jaywin
2
@Jaywin,System.exit(0);是一种非常糟糕的方法,尤其是在考试中。如果您想要立即显式退出方法,只需调用return即可。 - Filipp Voronov
1
除了返回之外,另一种选择是抛出异常。IllegalStateException 是一个不错的选择。 - fabian
@fabian,是的,但在这种情况下,这将违背任务规格。 - Filipp Voronov
@PhilipVoronov 我尝试了return,但它多次打印出了"This dog..."部分。我必须再看一下。 - Jaywin
@Jaywin,如果你想在没有打印“这只狗有太多跳蚤!”的情况下从hostFlea方法中返回5个跳蚤,请将System.out.println(...);行替换为return; - Filipp Voronov

1
我猜你被迫使用ArrayList。因此,你必须确保除了你的dog类之外,没有人修改列表。所以把List设为私有。
private ArrayList<Flea> fleas = new ArrayList<Flea>();

getDogFlea方法中返回一个副本并不暴露原始的List。

public ArrayList<Flea> getDogFlea() {
     return new ArrayList(fleas); //use copy constructor to not expose original list
}

在你的 hostFlea 方法中添加检查。
public void hostFlea(Flea flea) {
    if(fleas.size() == 5 ) {
        System.out.println("This dog has too many fleas!");
        return; //so the 6th element is not added
    }
    fleas.add(flea);
}

也许最后一个对于你的考试来说足够了,但在一个真正的程序中,getter会成为一个问题,确保永远不会超过5个元素。

2
返回一个不可修改的List而不是一个新的ArrayList会更好(尽管需要修改返回类型)。 - fabian
感谢您提供详细的答案。是的,这对我的考试答案非常有帮助,但我也看到了在实际情况下可能会出现的问题。不幸的是,我不确定在这门课程中还会学习多少Java,所以我想我没有更多时间去深入了解或改进它。 - Jaywin
没问题,但对于我参加过并了解的大多数Java考试来说,知道按引用调用和按值调用之间的区别很重要,即使在这个问题中并不重要,也许在以后会有更重要的问题;) - mszalbach

1
一只狗应该添加跳蚤的公共方法是hostFlea,因此您需要进行更改:
public void hostFlea(Flea flea) {
    // If the dog already has at least 5 fleas, you can't add another
    if (fleas.size() >= 5) {
        System.out.println("Your dog has too many fleas!");
    } else {
        fleas.add(flea);
    }
}

然而,getDogFlea() 返回了内部的 ArrayList,所以没有什么能够阻止有决心的用户调用 dog.getDogFlea().add(flea6)。为了防止这种行为,你可以复制数据:
public ArrayList<Flea> getDogFlea() {
     return new ArrayList<>(fleas);
}

或者,为了放宽API以返回一个List而不是ArrayList,教科书上的解决方案是使用Collections.unmodifiableList
public List<Flea> getDogFlea() {
     return Collections.unmodifiableList(fleas);
}

很好,你提到了防御性拷贝;这在返回引用类型的getter中很容易被忘记。 - Mick Mnemonic

0
在你的hostFlea方法中:-
在Dog类中将Flea对象添加到fleas ArrayList之前,只需检查此arraylist的大小。
像这样:-
public void hostFlea(Flea flea){
if(fleas.size() > 5) {
  System.out.println("This dog has too many fleas!");
        }
 else{
fleas.add(flea);
   }
}

谢谢你的回答,我只是把限制检查放错了位置。 - Jaywin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接