2013-08-13 4 views
0

Я хочу указать, является ли конкретный узел соседним с множеством узлов в определенном графе или нет? Для этого я написал этот метод:Специфический метод java возвращает исключение нулевого указателя

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

Новый метод работает отлично, но он требует огромного ресурса и времени и его бесполезности. Мой вопрос: Как я могу обработать исключение нулевого указателя таким образом, чтобы определенный метод занимал меньше времени для выполнения?

Я отлаживал свой метод. Вот информация о трех используемых объектах:

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 

Как вы можете видеть, ни один из указанных объектов не имеет значения! Так что могло бы вызвать NPE ?!

+2

Почему он выбрасывает исключение null-указателя? что получает нуль? – engma

+3

Ваш первый подход выглядит как лучший, и вы не объяснили детали NPE, которые вы получаете. Поле 'network'' null '? Как выглядит метод 'isSuccessor'? Кто-то передал коллекцию «null» или одну с «нулевой» записью? (Кроме того, когда вы пишете метод, вы должны быть гибкими в том, что вы принимаете. Конечно, вы можете взять любой «Список », а «Коллекция », вероятно, прекрасна.) – chrylis

+1

Прежде всего, когда вы получаете NPE, трассировка исключений скажет вам, где именно. Может быть, вы должны сказать нам. Во-вторых, возможно, вы должны отлаживать вещь, чтобы выяснить, какой указатель имеет значение null. –

ответ

1

Как я вижу, у вас есть два разных экземпляра одного и того же объекта в разных коллекциях. Из-за того, что вы поиск по названию, эти строки:

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

, а затем использовать метод isSuccessor для правильных экземпляров

Если мой assumtion правильно, то путь вы идете:

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

EDIT - Добавлены примечания: Это будет работать относительно быстро, но я верю в горлышко бутылки в сетевом объекте, и весь узел выглядит не очень хорошо для меня. Если есть метод, который возвращает CustomerNode по имени, тогда вам нужно использовать его для установки всех объектов в HashMap.

EDIT2 - Попробуйте сделать это быстрее. Я не знаю, какой пакет вы используете, но, возможно, jung-реализация DirectSparseGraph, если это так. Я нашел в источники Чжуна реализации способа getSuccessor:

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

и там нет isSuccessor. Я предположил, что ваш метод isSuccessor выбрасывает NPE, потому что метод getSuccessors возвращает null. Он возвращает значение null, потому что полученная вершина не может быть найдена. Вершины в коллекции сравниваются с использованием метода equals.Вот мой purpousal: определить равен метода в объекте клиента и сравните по имени (лучше определить равные и методы 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; 
    } 

Если вы не можете переопределить равно метод для объекта клиента, то вам нужно создавать фиктивные объекты, прежде чем передать их в объект сети, поэтому следующее условие должно быть правдой:

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

Но было бы лучше, если вы можете определить равные и методы hasCode Я считаю, что это существенно поможет вам.

+0

Это действительно интересно, это намного быстрее, чем тот, который я написал. Есть ли способ сделать это быстрее? Это часть огромного пробега, и это действительно поможет, если я сделаю эту часть самой быстрой. –

+0

Обновлен ответ – wolfroma

+0

WOW, ваш ответ определенно нужен + голосовать, к сожалению, я не мог проголосовать за то, что из-за репутации, Хоп кто-то делает это для меня. –

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

Это означает, что что-то всегда равно нулю. –

+0

@Alin А что скажет стек? На какой линии находится NPE? – ppeterka