1

我目前被困在代码的特定部分。对于我的班级,我们将创建一个包含载人或货物的棚车的火车。我们使用泛型来定义棚车是否可以载人或载货。然后我们将个人/货物加载到棚车上,如果它与已经在棚车上的人具有相同的字符串“ID”,那么我们记录一个错误并且不加载那个人/货物。这就是我遇到麻烦的地方。我一生都无法弄清楚如何比较他们的“ID”以查看它们是否相等。以下是我到目前为止的代码,

package proj5;

public class Person implements Comparable<Person> {

private String id;
private String name;
private int age;

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

public Person(String id){
    this.id = id;
}

public String getId(){
    return id;
}

public int getAge(){
    return age;
}

public String getName(){
    return name;
}

public String toString(){
    String str = "        " + "ID: " + id + "  " + " Name: " + name + "  " + " Age: " + age;
    return str;
}

public int compareTo(Person p) {
    int result = this.id.compareTo(p.getId());
    return result;
}

}

package proj5;

import java.util.ArrayList;
import java.util.List;
import java.util.Collections;

public class Boxcar<T extends Comparable<T>> {

private ArrayList<T> boxcar;
private int maxItems;
private int boxcarID;

public Boxcar(){
    boxcar = new ArrayList<T>();
}

public void load(T thing){
    for(int i = 0; i < boxcar.size(); i++){
    if(boxcar.size() < maxItems && !boxcar.get(i).equals(thing)){
        boxcar.add(thing);
        System.out.println(boxcar.get(i));
    }
    else{
        boxcar.remove(thing);
    }
    }
    Collections.sort(boxcar);
}

public int getBoxcarId(){
    return boxcarID;
}

public int getMaxItems(){
    return maxItems;
}

public void setMaxItems(int i){
    maxItems = i;
}

public void unload(T thing){
    for(T item : boxcar){
        if(item.equals(thing)){
            boxcar.remove(item);
        }
    }
}

public List<T> getBoxcar(){
    return boxcar;
}

public String toString(){
    String str = "";
    for(T item : boxcar){
        str += item + "\n";
    }
    return str;
}

}

问题出在我的加载功能上。我不知道如何比较他们的ID。为澄清起见,对象 ID 是字符串。我还有其他课程,但我只包括了我认为必要的课程。如果您需要更多文件,我很乐意提供。我已经坚持了几个小时,希望有任何帮助!非常感谢您!

编辑:我尝试使用 Collections API 中的 contains() 方法,但为什么这不起作用?听起来它会完美运行。

4

3 回答 3

1

You have to implement the equals and hashCode for your class Person.

The problem is that boxcar.get(i).equals(thing) is calling the generic equals and its only comparing the references.

so a generic equals will look like.

public boolean equals(Object obj){
  if (obj == null) return false;
  if (obj == this) return true;
  if (obj instanceof Person){
    Person p = (Person) obj;
    return p.getId().equals(this.getId());
  }
  return false;
}

and hashCode can be like this

public int hashCode(){
  return 37*this.getId().hashCode();
}
于 2012-12-10T04:46:13.677 回答
0

我认为问题在于boxcar = new ArrayList<T>();因为它可以包含人员/货物。如果它包含所有人对象,那么您的代码就可以了。但是因为它也可以包含货物,所以它显示了问题。

所以你能做的就是检查它的对象是否是人然后只检查比较。

public boolean equals(Object obj){
 if (obj instanceof Person){
   Person p = (Person) obj;
   return p.getId().equals(this.getId());
 }
 return true;
}

如果你重写 equals 方法,那么你还必须重写 hashCode方法

于 2012-12-10T04:51:35.860 回答
0

接受的答案可以供您使用,实际上可以用于测试相等性,但是考虑一下它确实会留下一个问题:因为您的Boxcar类是通用的,所以这将依赖于它所持有的已实现equals()hashcode(). 您的load()方法本身也有问题。

由于您使用<T extends Comparable<T>>then 限制泛型,因此您可以简单地执行以下操作:

if (boxcar.get(i).compareTo(thing) == 0) {

检查是否相等,因为compareTo()将返回0完全匹配。

您的load()方法不正确;ArrayList它一遍又一遍地迭代并添加相同的东西。为了满足您发布的标准,它需要类似于:

public void load(T thing) {
    boolean found = false;

    // Go through ArrayList and see if thing exists
    for (int i = 0; i < boxcar.size(); i++){
        if (boxcar.get(i).compareTo(thing) == 0) { 
            System.out.println(thing + " already exists");
            found = true;
            break;
        }
    }

    // If the thing didn't exist, add it, and sort the ArrayList    
    if (!found) {
        boxcar.add(thing);
        System.out.println("Added " + thing);
        Collections.sort(boxcar);
    }
}

现在它适用于您People和您的Cargo

现在......对于奖励积分,由于您ArrayList每次添加项目时都会对您的项目进行排序,因此您可以使用二进制搜索而不是线性搜索。方便的是,Java Collections 类中为此提供了一个——它依赖于一个排序列表,其中包含实现的东西Comparable

public void load(T thing) {

    // See if the thing exists. binarySearch returns an index if it's there
    // or a negative number if it's not
    if (Collections.binarySearch(boxcar, thing) >= 0) {
        System.out.println(thing + " already exists");
    } else {
        boxcar.add(thing);
        System.out.println("Added " + thing);
        Collections.sort(boxcar);
    }
}

由于评论而编辑添加:您还需要更改您的unload()方法。同样,我们compareTo()用于检查相等性。另外......一旦你找到它,你就不会打破你的循环。由于我们知道工作方式不能重复,load并且您永远不想在迭代列表时修改它:

public void unload(T thing){
    for(T item : boxcar){
        if(item.compareTo(thing) == 0) {
            boxcar.remove(item);
            break;
        }
    }
}

请注意,这里有一点细微差别。我们确保使用itemwith remove()。这是因为remove()依赖于equals()默认情况下将使用对象的引用值。item并且同等thing 比较,但是是同一类的两个不同实例。通过给remove()item知道从列表中删除实例。

更好的是,因为它更快并且避免了这种情况......binarySearch()通过索引使用和删除!

public void unload(T thing){
    int index = Collections.binarySearch(boxcar, thing);
    if (index >=0) {
        boxcar.remove(index);
    }
}
于 2012-12-10T05:18:18.410 回答