2

我得到了这个代码:

public Class Car;
{
    private String name;  
    public int number;     


    public Car(String name, int number) 
    {
        this.name = name;
        this.number = number;
    }

    // this class also got getters and setters 

然后我又上了一节课:

 public class CarList
    {
        private Collection<Car> cars;


        public CarList()
        {
            cars = new HashSet<>();
        }


       public boolean insertCar(Car car)
        {
            return cars.add(car); 
        }

然后代码继续使用其他一些方法,但它们没有问题。例如,如果我创建了两个 class 实例Carcar1(mazda,1)然后car2(porsche,2)我调用了 method insertCar,一切正常,方法返回,true因为有两辆车的名称和编号不同。

但是,如果创建例如car1(mazda,1)然后car2(porsche,1)方法也返回true,尽管汽车的数量是相同的。

编辑:所以我的问题是当我尝试“添加”具有相同编号和相同名称的汽车时如何强制方法返回false(那么@Override equals()方法将如何改变)?

4

6 回答 6

1

首先,您的Car课程不会按原样编译。Class应该是class,并且在 之后有一个分号Car。我只会认为这是一个错误。

对于您的任务,您必须在代码中进行以下修改:

  • 类中的覆盖equals()hashCode()方法Car,您只需考虑number对象比较的属性和哈希码计算。

    @Override
    public boolean equals(Object ob) {
        if (!ob instanceof Car) return false;
        Car that = (Car)ob;
        return this.number == that.number;
    }
    
    @Override
    public int hashCode() {
        return number;
    }
    
  • CarList课堂上,而不是Collection<Car>使用Set<Car>. 这将自动处理重复项。Set#add(E)方法Set仅在元素不存在时将元素添加到其中(这是基于equalsand进行测试的hashCode,这就是您需要覆盖它们的原因)。如果元素已经存在,那么它不会修改集合,并false根据需要返回。(糟糕,错过了您实际上HashSet仅在您的班级中实例化 a 。最好将引用重命名为Set<Car>)。


有关的:

于 2013-10-22T19:08:01.703 回答
0

假设你是 Java。

你有两个对象,需要弄清楚它们是否相同。一个是内存位置 1000000 的 Car,另一个是 1200000 的 Cat。看起来不同。完毕。

Java 做了一个额外的步骤:“对象有equals()方法吗?” 如果是这样,它会被调用,并且对象可以自己决定它是否等于另一个。如果不是,则回退到“它们是同一个实例吗?”

因此,如果您覆盖 equals() 方法,例如

@Override
public boolean equals(Object ob) {
  if (!(ob instanceOf Car)) { return false; }
  Car other = (Cat)ob;
  // decide whether they're equal and return true/false
}

那么这是朝着正确方向迈出的一步。

第二部分是hashCode()。合同是这样的:

如果 a1.equals(a2) 那么 a1.hashCode()==a2.hashCode()

因此,相同的对象必须产生相同的哈希码。然而,不同的对象也可能产生相同的哈希码。

于 2013-10-22T19:10:23.403 回答
0

有几个选项可供您选择,哪个最好取决于您CarList班级的使用场景。

对当前代码最直接的修改是在Add方法中添加一些代码,以遍历列表中的所有汽车并检查是否已经存在另一辆具有相同编号的汽车。如果是这样,则不要添加并返回 FALSE。

但是以上对于插入来说将具有二次性能,这对您来说可能不是很好。

相反,更好的选择是使用额外的数据结构,例如HasSet列表中已经存在的所有车号。添加时,检查集合是否有重复,如果您添加的数字已经存在,则返回 false。

HashSet<Integer> carNumbers = new HashSet<Integer>();
public boolean insertCar(Car car)
{
    if(!carNumbers.contains(car.getNumber()))
    {
        carNumbers.put(car.getNumber());
        return cars.add(car); 
    }

    return false;
}
于 2013-10-22T19:07:58.893 回答
0

修改你的类如下: Car

public class Car {

private String name;
public int number;

public Car(String name, int number) {
    this.name = name;
    this.number = number;
}

@Override
public boolean equals(Object ob) {
    if (!(ob instanceof Car)) {
        return false;
    }
    Car car = (Car) ob;
    return this.number == car.number;
}

@Override
public int hashCode() {
    return number;
}
}

汽车清单

public class CarList {

private Set<Car> cars;

public CarList() {
    cars = new HashSet<Car>();
}

public boolean insertCar(Car car) {
    return cars.add(car);
}

}

于 2013-10-22T19:19:46.030 回答
0

您需要覆盖equals. Car在该方法中,提供您想要确定两个对象是否相同的逻辑。

@override
public boolean equals(Car car) {
   return car.name == this.name && car.number == this.number;
}

或者您希望该方法满足的任何条件。

于 2013-10-22T19:09:14.843 回答
0

HashSet 的答案会起作用,但他们假设在任何用例中您永远不会想要两辆具有相同编号和不同名称的汽车。

如果您只想在此用例中使用此行为(例如,数字在 CarList 中是唯一的,但通常不是),您可以使用带有自定义比较器的 TreeSet。作为附加功能,列表将自动按数字排序。

cars = new TreeSet<>(new Comparator<>(){
    public int compare(Car a, Car b){
       return a.number - b.number;
    }
});

在这种情况下,您不需要实现 equals() 或 hashCode()。

于 2013-10-22T19:16:57.883 回答