比较通用商品?

时间:2012-12-10 04:36:11

标签: java generics compare project

我目前停留在代码的特定部分。对于我的班级,我们要创建一个包含载有人或货物的箱子的火车。我们使用泛型来定义一个棚车是否可以容纳人或货物。然后我们将个人/货物装载到棚车上,如果它与已经在棚车上的人具有相同的字符串“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()方法,但为什么不起作用?听起来它会完美运作。

3 个答案:

答案 0 :(得分:1)

您必须为您的Person类实现equals和hashCode。

问题在于boxcar.get(i).equals(thing)正在调用泛型等号,而只是比较引用。

所以通用等于看起来像。

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;
}

和hashCode可以是这样的

public int hashCode(){
  return 37*this.getId().hashCode();
}

答案 1 :(得分: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方法

答案 2 :(得分:0)

接受的答案对你的使用是好的,实际上可以用来测试相等性,但是考虑一下它确实会留下问题:因为你的Boxcar类是Generic,这将依赖于任何它坚持实施equals()hashcode()。您的load()方法本身也存在问题。

由于您使用<T extends Comparable<T>>限制通用,因此您可以执行以下操作:

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);
    }
}

现在它适用于您的PeopleCargo

现在......对于奖励积分,因为您每次添加项目时都要对ArrayList进行排序,您可以使用二分搜索而不是线性搜索。方便的是,Java Collections class中提供了一个 - 正是这一点 - 它依赖于一个排序列表,其中包含实现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;
        }
    }
}

注意这里有一点点细微差别。我们务必将itemremove()一起使用。这是因为remove()依赖于equals(),默认情况下它将使用对象的引用值。 itemthing 比较,但它们是同一个类的两个不同实例。通过提供remove() item,它知道从列表中删除实例。

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

public void unload(T thing){
    int index = Collections.binarySearch(boxcar, thing);
    if (index >=0) {
        boxcar.remove(index);
    }
}