2013-08-13 6 views
0

정의 된 그래프에서 특정 노드가 노드 집합과 이웃인지 여부를 지정 하시겠습니까? 이 목적을 위해이 메소드를 작성했습니다 :특정 Java 메소드 반환 null 포인터 예외

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

불행히도이 메소드는 널 포인터 예외를 리턴합니다. 그래서 나는 그것을 다음과 같이 변경하기로 결정했다 :

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

새로운 방법은 잘 작동하지만 엄청난 자원과 시간과 그 쓸모가 없다. 내 질문은 어떻게 정의 된 메서드를 실행 시간이 적게 걸리는 방식으로 널 포인터 예외를 처리 할 수 ​​있습니까?

내 방법을 디버깅했습니다. 다음은 사용 된 세 객체에 대한 정보입니다.

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가 원인이 될 수 있습니다!

+2

왜 null 포인터 예외가 발생합니까? null이되는 것은 무엇입니까? – engma

+3

첫 번째 접근법이 더 좋은 것으로 보이고 NPE에 대한 세부 사항을 설명하지 않았습니다. 'network' 필드가'null'입니까? 'isSuccessor' 메소드는 어떻게 생겼을까요? 누군가가'null' 컬렉션이나'null' 엔트리가있는 컬렉션을 전달 했습니까? (또한, 당신이 방법을 쓰고있을 때 당신은 받아 들일 수있는 것에 융통성을 가져야한다. 어떤 목록을 가져올 수도 있고, Collection 도 괜찮을 것이다.) – chrylis

+1

먼저 NPE를 얻을 때 예외 추적을 통해 정확한 위치를 알려줍니다. 어쩌면 우리에게 말해야 할 것입니다. 둘째, 실제로 어떤 포인터가 null인지 파악하기 위해 디버그해야합니다. –

답변

1

앞에서 보았 듯이 서로 다른 컬렉션에 동일한 오브젝트의 두 인스턴스가 있습니다. 그 때문에 당신이 이름으로 검색 않으며,이 라인 :

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

내 assumtion 잘 다음 방법으로 당신이가는 경우 다음 올바른 인스턴스

에 대한 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의 출처에서 getSuccessor 메소드의 구현을 찾았습니다.

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

및 isSuccessor가 없습니다. getSuccessors 메서드가 null을 반환하기 때문에 isSuccessor 메서드가 NPE를 throw한다고 가정했습니다. 전달 된 정점을 찾을 수 없으므로 null을 반환합니다. 컬렉션의 정점은 equals 메서드를 사용하여 비교됩니다.여기 내 purpousal은 다음과 같습니다 고객 객체의 equals 메소드 정의하고 이름을 비교 (더 나은 함께 등호와 hashCode 메소드를 정의하고 IDE에서 그들을 생성 - 이클립스, IDEA, 넷빈즈) : 당신이 사용 시도 할 수 있습니다 그 후

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

을 당신이 필요로하는 다음 고객 개체에 대한 방법과 동일

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

을하지만 당신은 내가 크게 도움이 될 것입니다 생각 같고 hasCode 방법을 정의 할 수 있다면 더 좋을 것 : 다음 조건이 참이어야한다, 그래서 mock 객체 전에, 네트워크 객체로 전달 만들 수 있습니다.

+0

정말 흥미 롭습니다. 제가 작성한 verion보다 훨씬 빠릅니다. 빨리 할 수있는 방법이 있습니까? 거대한 달리기의 일부이며,이 부분을 가장 빨리 만드는 것이 도움이 될 것입니다. –

+0

대답을 – wolfroma

+0

WOW, 당신의 대답은 분명히 투표가 필요합니다, 불행히도 나는 투표 할 수 없었기 때문에 명성 때문에, 누군가 나를 위해 그것을 할 수 있습니다. –

0

나는이 당신을 위해 무엇을 찾고 있는지 모르겠지만 그것이 "마이크로 최적화"당신은 아마이 도움이 될 것입니다, 필요하다면 : 널 (null)에 대한

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

확인 이웃 분석을 진행하기 전에이 . 예 :

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를 피하기 위해 함수에있는 모든 인수를 확인해야합니다.

+0

실제로 문제는 다른 개체로 인해 발생합니다. 이 메서드를 호출하여 보낸 지정된 개체는 네트워크 정점 그 자체가 아닙니다. 따라서이 검사 과정을 추가하면 도움이되지 않을 것입니다. 제가 작성한 두 번째 방법을 보면 제가 의미하는 바를 알 수 있습니다. –

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 

} 
+0

이 메서드는 내 경우 항상 false를 반환합니다. –

+0

뭔가가 항상 null임을 의미합니다. –

+0

@Alin 그리고 스택 추적은 무엇을 말합니까? NPE는 어느 라인에 있습니까? – ppeterka