6

簡単な質問があります。次のようなフィールドを持つクラス Product があります。

private Integer id;
private String category;
private String symbol;
private String desc;
private Double price;
private Integer quantity;

ID に基づいて LinkedHasSet から重複アイテムを削除したい。たとえば、同じ ID を持つが数量が異なる製品がセットに追加され、同じ ID を持つ製品を削除 (更新) したい。それをするために?

例: 製品: id=1、カテゴリ=CCTV、シンボル=TVC-DS、desc=シンプル カメラ、価格=100.00、数量=1 製品: id=1、カテゴリ=CCTV、シンボル=TVC-DS、desc=シンプル カメラ、価格=100.00、数量=3

セットに追加されません

私のコード:

    public void setList(Set<Product> list) {
    if(list.isEmpty()) 
        this.list = list;
    else {
        this.list.addAll(list);
        Iterator<Product> it = this.list.iterator();
        for(Product p : list) {
            while(it.hasNext()) {
                if(it.next().getId() != p.getId())
                    it.remove();
                    this.list.add(p);   
            }
        }
    }
}
4

5 に答える 5

17

すべてのSet実装で重複が削除されLinkedHashSetます。これも例外ではありません。

複製の定義は、方法によれば、互いに等しい 2 つのオブジェクトですequals()。クラスをオーバーライドequalsしていないProduct場合、同じ値を持つ異なるインスタンスではなく、同一の参照のみが等しいと見なされます。

そのため、クラスにequals(and )のより具体的な実装を追加する必要があります。hashcodeいくつかの例とガイダンスについては、 Java での equals と hashcode のオーバーライドを参照してください。(オーバーライドする必要があることに注意してくださいhashcode。そうしないと、クラスはハッシュ セットで正しく動作しません。)

于 2013-02-07T09:53:27.913 に答える
2

正直な答えはしませんが、いくつかアドバイスをします。

  1. 入れたい場合はProductSetそのメソッドを実装する必要がequals()ありhashCode()ます。
  2. 実装するときは、手段の「平等」equals()を決定する必要があります(「平等」に関しては1つのインスタンスのみを含めることができます)。たとえば、2つのインスタンスが「等しい」場合、それらが同じIDを持っていれば十分ですか、それとも数量も考慮に入れる必要がありますか?あなたの場合、この質問に答えるのは簡単ではありませんが、読んでください。ProductSetProduct
  3. 通常、このような状況ではIDのみが考慮されます。Productその場合、メモリ内に異なる2つのインスタンスを含めるべきではありませんquantities。それらの1つは、正しくない状態を表すためです(つまり、特定の製品の数量は、一度に両方ではなく、1または3のいずれかになります)。
  4. デザインが完全に正しくないと思います。Productあなたの場合のクラスは一般的な製品の説明(価格を含む)を表しているので、quantity実際にはそこに適合しません。誰かがコピーをいくつか注文できる場合は、注文する製品とそれに対応する数量を指定する、またはProductなどの別のクラスを作成する必要があると思います。例:OrderOrderLine

    class OrderLine {
      private Product product;
      private Integer quantity; 
    }
    

    このような設計では、ポイント2からの質問に簡単に答えることができProduct.equals()ます。IDのみ、およびOrderLine.equals()製品(ID)数量の両方を比較する必要があります。

于 2013-02-07T10:06:47.000 に答える
1

同じコードで等しい ID を持つ要素をハッシュする方法で、独自のハッシュ関数を実装することをお勧めします。これにより、明示的にコーディングする必要なく、問題が解決されます。

于 2013-02-07T09:54:01.103 に答える
0

他の人がすでに言ったように、あなたは(オーバーライド)equals()hashCode()そして(おそらく)インターフェースcompareTo()から実装する必要がありComparableます。これらのメソッドは、正しく実装されていない場合、予期しない実行時の動作につながる可能性があります。問題をデバッグするのは難しい。したがって、、を使用してこれらのメソッドを実装することをお勧めApache Commons EqualsBuilderHashcodeBuilderますComparableBuilder。使用方法の例は、このリンクhttp://www.javaworld.com/community/node/1859Apache Commons builderで見ることができます

于 2013-02-07T10:06:35.720 に答える
0

コードがリストに 2 回追加されているようです。呼び出し中にaddAll()1 回、反復中にもう一度。この場合、2回目の繰り返しで十分だと思います。比較は、equals代わりに使用するように変更する必要があります==

public void setList(Set<Product> list) {
    if(list.isEmpty()) 
        this.list = list;
    else {
        //this.list.addAll(list); Do not add all
        Iterator<Product> it = this.list.iterator();
        for(Product p : list) {
            while(it.hasNext()) {
                if(it.next().getId().equals(p.getId()))
                {
                    this.list.add(p);
                }   
            }
        }
    }
}
于 2013-02-07T09:54:48.350 に答える