我想指定特定节点是否与定义图中的节点集相邻?为此,我写了这个方法:
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?!
答案 0 :(得分:1)
正如我所看到的,对于不同的集合,您有两个不同的同一对象实例。因此,您可以按名称搜索,这些行:
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 - 尝试加快速度。 我不知道你使用的包,但如果是这样,可能是jung实现的DirectSparseGraph。我在jung的源代码中找到了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:在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方法会更好,我相信它会对你有很大帮助。
答案 1 :(得分: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;
}
答案 2 :(得分: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;
}
同样,您必须对函数中的所有参数进行null检查以避免NPE。
答案 3 :(得分: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
}