0

特定のノードが、定義されたグラフ内の一連のノードと隣接しているかどうかを指定したいですか? この目的のために、私はこの方法を書きました:

private boolean isNeighbor(ArrayList<Customer> collection, Customer node,DirectedSparseGraph<Customer, Transaction> network) throws SQLException {
        for(Customer customer:collection){
            if(network.isSuccessor(customer, node)) return true;
        }
        return false;
    }

残念ながら、このメソッドは null ポインター例外を返します。だから私はそれを次のように変更することにしました:

private boolean isNeighbor(ArrayList<Customer> collection, Customer node,DirectedSparseGraph<Customer, Transaction> network) throws SQLException {
        Collection<Customer> nodes=network.getVertices();
        ArrayList<Customer> acctualNodes = new ArrayList<Customer>();
        Customer acctualNode=new Customer();
        for(Customer customer: collection){
            for(Customer cust:nodes){
                if(cust.getName().equals(customer.getName())) acctualNodes.add(cust);
            }
        }
        for(Customer customer: nodes){
            if(node.getName().equals(customer.getName())) acctualNode=customer;
        }
        for(Customer customer: acctualNodes){
            if(network.isSuccessor(customer, acctualNode)) return true;
        }
        return false;
    }

新しい方法は問題なく機能しますが、膨大なリソースと時間がかかり、役に立ちません。私の質問は、定義されたメソッドの実行時間が短縮されるように、null ポインター例外を処理するにはどうすればよいですか?

メソッドをデバッグしました。使用した 3 つのオブジェクトに関する情報は次のとおりです。

collection: ArrayList<E> id=17
elementData Object[6246]  (id=37)   

node: Customer id=23
customerArray   null    
customerName    "9379090484" (id=1345)  
type    null    

network: DirectedSparseGraph<V,E> id=27
edge_type   EdgeType  (id=39)   
edges   HashMap<K,V>  (id=42)   
vertices    HashMap<K,V>  (id=47)   
entrySet    HashMap$EntrySet  (id=1349) 
hashSeed    -949367244  
keySet  HashMap$KeySet  (id=48) 
loadFactor  0.75    
modCount    64780   
size    64780   
table   HashMap$Entry<K,V>[131072]  (id=52) 
threshold   98304   
useAltHashing   false   
values  null

ご覧のとおり、指定されたオブジェクトはどれも null ではありません! では、何が NPE を引き起こしたのでしょうか?!

4

4 に答える 4

1

ご覧のとおり、同じオブジェクトの 2 つの異なるインスタンスが異なるコレクションに含まれています。そのため、名前で検索します。これらの行は次のとおりです。

for(Customer customer: collection){
    for(Customer cust:nodes){
        if(cust.getName().equals(customer.getName())) acctualNodes.add(cust);
    }
}

次に、正しいインスタンスに isSuccessor メソッドを使用します

私の仮定が正しければ、あなたの行く道は次のとおりです。

private boolean isNeighbor(ArrayList<Customer> collection, Customer node,DirectedSparseGraph<Customer, Transaction> network) throws SQLException {
        HashMap<String, Customer> realNodes = new HashMap<String, Customer>();
        Collection<Customer> nodes=network.getVertices();

        for (Customer n: nodes) {
            realNodes.put(n.getName(), n);
        }

        Customer acctualNode = realNodes.get(node.getName());
        for(Customer customer:collection){
            Customer actualCustomer = realNodes.get(customer.getName());
            if(network.isSuccessor(actualCustomer, acctualNode)) {
                return true;
            }
        }
        return false;
    }

編集 - 追加されたメモ: これは比較的高速に動作しますが、ネットワーク オブジェクトにボトルネックがあると考えています。すべてのノードを取得するのは適切ではありません。名前で CustomerNode を返すメソッドがある場合は、すべてのオブジェクトを HashMap に入れる代わりにそれを使用する必要があります。

EDIT2 - 高速化してみてください。あなたが使用しているパッケージはわかりませんが、そうであれば、おそらく DirectSparseGraph の jung 実装です。jung のソースで getSuccessor メソッドの実装を見つけました。

public Collection<V>  getSuccessors(V vertex)
    {
        if (!containsVertex(vertex))
            return null;
        return Collections.unmodifiableCollection(getSuccs_internal(vertex));
    }

isSuccessor はありません。getSuccessors メソッドが null を返すため、isSuccessor メソッドが NPE をスローすると仮定しました。渡された頂点が見つからないため、null を返します。コレクション内の頂点は equals メソッドを使用して比較されています。ここに私の目的があります: Customer オブジェクトで equals メソッドを定義し、名前で比較します (equals メソッドと hashCode メソッドを一緒に定義し、IDE - Eclipse、IDEA、NetBeans から生成する方が良い):

public class Customer {
...
 private String name;

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

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Customer other = (Customer ) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
}

その後、最初のアプローチを試すことができます。それが機能しない場合は、 isSuccessor メソッドと NPE に関する私の仮定が正しくないため、 isSuccessor メソッドを自分で定義してみてください。

private boolean isNeighbor(ArrayList<Customer> collection, Customer node,DirectedSparseGraph<Customer, Transaction> network) throws SQLException {
        for(Customer customer:collection){
            //if(network.isSuccessor(customer, node)) { 
            if(isSuccessor(network, customer, node)) {
                return true;
            }
        }
        return false;
    }

    private boolean isSuccessor(DirectedSparseGraph<Customer, Transaction> network, Customer customer, Customer node) {
        Customer mockNode = node;
        Customer mockCustomer = customer;
        // If you can't redefine equals method for Customer object then you need to create a mock object mockNode.equals(node) == true && mockCustomer.equals(customer)
        Collection<Customer> successors = network.getSuccessors(mockNode);
        return successors != null && successors.indexOf(mockCustomer) != -1;
    }

Customer オブジェクトの equals メソッドを再定義できない場合は、ネットワーク オブジェクトに渡す前にモック オブジェクトを作成する必要があるため、次の条件が満たされている必要があります。

mockNode.equals(node) && mockCustomer.equals(customer)

しかし、equals メソッドと hasCode メソッドを定義できればもっとよいでしょう。

于 2013-08-13T12:42:43.397 に答える
0

これがあなたが探しているものかどうかはわかりませんが、必要な「マイクロ最適化」が必要な場合は、おそらくこれが役立ちます。

private boolean isNeighbor(ArrayList<Customer> collection, Customer node,DirectedSparseGraph<Customer, Transaction> network) throws SQLException {
    if (network == null) {
        throw new IllegalArgumentException("Network may not be null.");
    }

    if (collection == null) {
        return false;
    }

    for(Customer customer : collection){
        if(network.isSuccessor(customer, node)) {
            return true;
        }
    }

        return false;
}
于 2013-08-13T11:43:05.233 に答える
0

以下でもいけます。

private boolean isNeighbor(ArrayList<Customer> collection, Customer node,DirectedSparseGraph<Customer, Transaction> network) throws SQLException {
    boolean isNeighbor = false;
    try {
        for(Customer customer:collection) {
            if (network.isSuccessor(customer, node)) {
                isNeighbor = true;
                break;
            }
        }
    }
    catch (NullPointerException npe) {
        npe.printStackTrace();
        isNeighbor = false;
    }

    return isNeighbor

}
于 2013-08-13T11:54:30.953 に答える
0

近隣分析に進む前に null をチェックします。例えば。

private boolean isNeighbor(ArrayList<Customer> collection, Customer node, DirectedSparseGraph<Customer, Transaction> network) throws SQLException {
    if (null == collection || collection.size() == 0) {
        return false;
    } else {
        for (Customer customer : collection) {
            if (network.isSuccessor(customer, node)) return true;
        }
    }
    return false;

}  

同様に、NPE を回避するために、関数内のすべての引数に対して null チェックを行う必要があります。

于 2013-08-13T11:45:21.850 に答える