2

カスタムのデータをTreeSet. カスタム数が同じ場合は、出来高を足します。

これがInteratorTradeNodeを実装する私のクラスです。Comparable

import java.util.Comparator;  

public class TradeNode implements Comparable<TradeNode> {  

    private String cstm; // custom number  

    private Integer mon = 0; // Trade  

    public TradeNode() {}  

    public TradeNode(String cstm, int mon) {  
        this.mon = mon;  
        this.cstm = cstm;  
    }  

    public int compareTo(TradeNode o) {  
        if (o.cstm.equals(this.cstm)) {  
            o.mon += this.mon;  
            return 0;  
        } else if (this.mon == o.mon) {  
            return this.cstm.compareTo(o.cstm);  
        } else {  
            //return (o.mon - this.mon);  
            return o.mon.compareTo(this.mon);  
        }  
    }  

    @Override  
    public boolean equals(Object obj) {  
        if (this == obj) {  
            return true;  
        }  
        if (obj == null) {  
            return false;  
        }  
        if (!(obj instanceof TradeNode)) {  
            return false;  
        }  
        TradeNode other = (TradeNode) obj;  
        if (cstm == null) {  
            if (other.cstm != null) {  
                return false;  
            }  
        } else if (!cstm.equals(other.cstm)) {  
            return false;  
        }  
        return true;  
    }  

    @Override  
    public int hashCode() {  
        final int prime = 31;  
        int result = 1;  
        result = prime * result + ((cstm == null) ? 0 : cstm.hashCode());  
        return result;  
    }  

    @Override  
    public String toString() {  
        return "[" + cstm + "] [" + mon + "]";  
    }  

    public int getMon() {  
        return mon;  
    }  

    public void setMon(Integer mon) {  
        this.mon = mon;  
    }  

    public String getCstm() {  
        return cstm;  
    }  

} 

テストクラスは次のとおりです。

public class Testtree {  
    public static void main(String[] args) {  
    TradeNode nd1 = new TradeNode("A", 100);  
        TradeNode nd2 = new TradeNode("B", 10);  
        TradeNode nd3 = new TradeNode("B", 1000);  
        TreeSet<TradeNode> tree = new TreeSet<TradeNode>();  
        tree.add(nd1);  
        tree.add(nd2);  
        tree.add(nd3);  
        for (TradeNode node : tree) {  
            System.out.println(node);  
        }  
    } 

出力は次のようになるはずです:

[B] [1010]  
[A] [100]

しかし、出力は

[B] [1000]  
[A] [100] 
[B] [10]

誰かが私を助けて、私の過ちを指摘してくれませんか?

このように compareTo() メソッドを変更しても、まだ機能しません。

public int compareTo(TradeNode o) {
        if (o.cstm.equals(this.cstm)) {
            return 0;
        } else {
            return o.mon.compareTo(this.mon);
        }
    }

結果は次のとおりです。

[B] [1000]
[A] [100]
[B] [10]

Ben Xuのメソッドを試してみました。コードは次のとおりです: 私の新しい compareTo() メソッド:

public int compareTo(TradeNode o) {
        if (o.cstm.equals(this.cstm)) {
            return 0;
        } else {
            return this.mon.compareTo(o.mon);
        }
    }

私の新しい Testtree クラス:

public class Testtree {

    public static void main(String[] args) {
        TradeNode nd1 = new TradeNode("44010358010481", 150354);
        TradeNode nd2 = new TradeNode("44010358010481", 150641);
        TradeNode nd3 = new TradeNode("44010358010481", 270000);
        TradeNode nd4 = new TradeNode("44010039275685", 10000);
        TradeNode nd5 = new TradeNode("44010039275685", 980000);
        TradeNode nd6 = new TradeNode("44010039275685", 5000);
        TradeNode nd7 = new TradeNode("44010234235687", 10000);
        TradeNode nd8 = new TradeNode("44010234235687", 360000);
        TradeNode nd9 = new TradeNode("44010234235687", 53400);
        Map<String, Integer> map = new HashMap<String, Integer>(); 
        addTradeNode(map, nd1);
        addTradeNode(map, nd2);
        addTradeNode(map, nd3);
        addTradeNode(map, nd4);
        addTradeNode(map, nd5);
        addTradeNode(map, nd6);
        addTradeNode(map, nd7);
        addTradeNode(map, nd8);
        addTradeNode(map, nd9);

        Iterator<Entry<String, Integer>> iterator = map.entrySet().iterator();
        TradeNode t;
        List<TradeNode> list = new ArrayList<TradeNode>();
        while(iterator.hasNext()) {
            Map.Entry<String, Integer> m = iterator.next();
            t = new TradeNode(m.getKey(),m.getValue());
            list.add(t);
        }
        Collections.sort(list);
        for(TradeNode tn : list) {
            System.out.println(tn);
        }
    }

    private static void addTradeNode(Map<String, Integer> map, TradeNode node) {

        Integer integer = map.get(node.getCstm());
        if (integer == null) {
            map.put(node.getCstm(), node.getMon());
        } else {
            map.remove(node.getCstm());
            map.put(node.getCstm(), integer.intValue() + node.getMon());
        }

    }

}

結果は次のとおりです。

[44010234235687] [423400]
[44010358010481] [570995]
[44010039275685] [995000]

最後に、それは私の要件を満たしました。しかし、この新しい compareTo() メソッドが次のテスト メソッドで機能しない理由はまだわかりません。

public class Testtree2 {

    public static void main(String[] args) {
        TradeNode nd1 = new TradeNode("A", 100);
        TradeNode nd2 = new TradeNode("B", 10);
        TradeNode nd3 = new TradeNode("B", 1000);
        TreeSet<TradeNode> tree = new TreeSet<TradeNode>();
        tree.add(nd1);
        tree.add(nd2);
        tree.add(nd3);
        for (TradeNode node : tree) {
            System.out.println(node);
        }       
    }
}

結果は次のとおりです。

[B] [10]
[A] [100]
[B] [1000]

そして、私はそれが次のようになると思いました:

[B] [10]
[A] [100]

新しいcompareTo()メソッドのどこに問題があるのか​​誰か教えてもらえますか? どうもありがとう、そして私を助けてくれた人に感謝します。

ははは、JavaRanch から回答がありました。ヘンリーという人が答えを教えてくれました。ここで、TreeSet で contains() メソッドを使用すると、この Set 内のすべてを検索するのではなく、並べ替えられた値のみを検索すると思います。

新しい Testtree3 クラスは次のとおりです。

public class Testtree3 {

    public static void main(String[] args) {
    TradeNode nd1 = new TradeNode("A", 100);
        TradeNode nd2 = new TradeNode("B", 200);
        TradeNode nd3 = new TradeNode("B", 1000);
        TreeSet<TradeNode> tree = new TreeSet<TradeNode>();
        tree.add(nd1);
        tree.add(nd2);
        tree.add(nd3);
        for (TradeNode node : tree) {
            System.out.println(node);
        }
    }

}

結果は次のとおりです。

[A] [100]
[B] [200]

ハハ。次に、TreeSet の背後にあるコードを探しに行きます。

4

4 に答える 4

4

TreeSet.addあなたが思っていることをしません。

値が既に存在することを検出した場合、新しい値を既存の値に「追加」しようとはしません。セットを変更せずに単に戻ります。それは単なるセットベースの操作です。

(さらに、比較がメソッドと同期していないという事実はequals少し奇妙であり、 の比較は にthis.mon == o.monは不適切ですInteger。)

于 2011-07-10T11:45:39.027 に答える
0

で引数を変更するべきではありませんTradeNode#compareTo(...)TreeSetが呼び出されるかどうかnewItem.compareTo(existingItem)、またはexistingItem.compareTo(newItem)比較を行うときに保証されません。

ミューテーションなしでコントラクトをTradeNode#compareTo(...)満たすように修正する必要があります。Comparator

含まれているオブジェクトを変更したい場合、a Set(またはそれ以外) が実際に正しいデータ構造であるかどうかはわかりません。TreeSetおそらく、MapからStringTradeNodeのほうがより良い選択でしょうか?

于 2011-07-10T12:31:14.063 に答える
0

実行結果は です。チェックして、プログラムを再度実行できます。

[B] [1000]
[A] [100]
[B] [10]

結果は、ツリーセットが実装されたコンパレータを使用するためです

あなたが何をしたいのかわかりません。

しかし、少なくとも 1 つの明らかな悪い習慣があります。

public int compareTo(TradeNode o) {  
    if (o.cstm.equals(this.cstm)) {  
        o.mon += this.mon;  
        return 0;  
    } else if (this.mon == o.mon) {  
        return this.cstm.compareTo(o.cstm);  
    } else {  
        //return (o.mon - this.mon);  
        return o.mon.compareTo(this.mon);  
    }  
}  

compareTo メソッドでその値を変更しないでください。」、これは非常に紛らわしいです。

すべての TreeNode を同じ名前で合計したい場合は、 Collection を使用せず、代わりに map を使用してください。

たとえば、ハッシュマップを使用し、キーは名前または (等号で、ハッシュコードは cstm のみを使用するため TreeNode )、値は num です。TreeNode を追加するたびに、同じ名前が存在するかどうかを確認し、存在しない場合はマップに追加し、そうでない場合は値を追加します。

以下は、マップを使用したコードの例です。

public class Testtree {
public static void main(String[] args) {
    TradeNode nd1 = new TradeNode("A", 100);
    TradeNode nd2 = new TradeNode("B", 10);
    TradeNode nd3 = new TradeNode("B", 1000);
    Map<String, Integer> map = new HashMap<String, Integer>();
    addTreeNode(map, nd1);
    addTreeNode(map, nd2);
    addTreeNode(map, nd3);
    System.out.println(map);
}

private static void addTreeNode(Map<String, Integer> map, TradeNode node) {

    Integer integer = map.get(node.getCstm());
    if (integer == null) {
        map.put(node.getCstm(), node.getMon());
    } else {
        map.remove(node.getCstm());
        map.put(node.getCstm(), integer.intValue() + node.getMon());
    }

}
}
于 2011-07-10T12:32:50.400 に答える
0

o.mon += this.mon;あなたの compareTo メソッドには、非常に悪い設計であるstate を変更するコードが含まれており、さらに悪いことに、その状態は compareTo の結果を決定するために使用されif (this.mon == o.mon)ます。この有毒な関係が存在するため、実装はほぼ確実に compareTo の契約に違反しています: javadoc を参照してください。

これは恐ろしい。compareTo メソッドで、副作用によるスタイル状態の変更を取り除きます。

public int compareTo(TradeNode o) {  
    if (o.cstm.equals(this.cstm)) {  
        o.mon += this.mon;    // ALARM BELLS!!! SIDE EFFECT!! ARRGGGHHH!
        return 0;  
    } else if (this.mon == o.mon) {  // AND THE SIDE EFFECT IS ALSO USED TO COMPARE! AVERT YOUR EYES! 
        return this.cstm.compareTo(o.cstm);  
    } else {  
        //return (o.mon - this.mon);  
        return o.mon.compareTo(this.mon);  
    }  
}  
于 2011-07-10T12:35:02.860 に答える