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

クラスPersonのequalsとhashCodeを実装する必要があります。

問題はboxcar.get(i).equals(thing)、ジェネリックequalsを呼び出し、参照を比較することだけです。

したがって、一般的な等しいは次のようになります。

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();
}
于 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>>ようにすることができます。

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コレクションクラスで提供されています。これは、以下を実装するものを保持するソートされたリストに依存しています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;
        }
    }
}

ここにはわずかなニュアンスがあることに注意してください。必ずと一緒に使用itemしてremove()ください。これは、デフォルトでオブジェクトの参照値を使用することremove()に依存しているためです。等しく比較しますが、同じクラスの2つの異なるインスタンスです。与えることにより、リストからそのインスタンス を削除することがわかります。equals()itemthing 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 に答える