将边缘存储在数据结构中

问题描述

| 我有一个名为Edge的类,它具有属性源ID,目标ID和权重。我想将此边缘存储在集合数据结构中,因此在集合中不会有边缘的重复(即:具有相同源ID和目标ID的边缘)。 问题是这样的: 我想向该数据结构添加Edge。如果数据结构中已经存在某个边缘,则无需再次添加它,我只需要将现有边缘的权重与我要添加的边缘相加即可。 我很确定我必须重写集合的add函数。有人可以给我一个指示吗?为此,在Java中使用的最佳数据结构是什么?     

解决方法

一些建议。 您想要的基础数据结构可能是一个映射(HashMap可能是最好的具体实现),而不是一个集合。密钥应该是(源,目标)对,并且值可以是Edge对象。如果您非常担心重复,可以采用多种方法来解决,其中一种方法是只存储权重作为值。 其次,这需要Graph类。如果接口设计得当,它将隐藏内部实现细节。我建议高度使用合成而不是继承。换句话说,您的图具有-映射,而不是-映射。 还可以看看现有的代码,例如JGraphT,它已经具有加权有向图,与您在上面描述的一样。有时最好不要从头开始重新发明。 祝好运。     ,一种替代方法是将一组边缘包装在您自己的类中,这恰好提供了您希望支持的接口。 这是在合成和继承之间进行选择的特定情况。通常,组合比继承更可取,尽管它也有它的位置。 例如,这是一个可能的类的粗略草图(编辑:使用地图)
   public class Edge { ... }

   public class EdgeData { 
       public Edge getEdge() { ... }
       public float getWeight() { ... }
   }

   public class Edges {
       private Map<Edge,EdgeData> m_edges = new HashMap<Edge,EdgeData>();
       public addEdge( EdgeData edge ) { 
            // Do what you\'ve said above.

       }
       public Map<Edge,EdgeData> getEdges() { return Collections.unmodifiableMap( m_edges ); }
   }
    ,好吧,Set.add()方法返回一个布尔值,该布尔值指示是否将新项目成功添加到集合中。如果返回false,则是因为该项目已经存在。基于此,您可以轻松编写算法。丑陋的部分必须迭代集合以更新值,对吗?
if(!edges.add(newEdge)){
   Iterator<Edge> iter = edges.iterator();
   while(iter.hasNext()){
    Edge edge = iter.next();
    if(edge.equals(newEdge)){
        edge.updateWeight(newEdge.getWeight()); //this.weight+=moreWeight
    }
   }
}
基于此,我假设您想要的只是美化所有这些迭代样板代码的方法。 我喜欢的解决方案是使用LambdaJ Collections更新现有Edge的权重。
if (!edges.add(newEdge)) {
   with(edges).first(is(newEdge)).updateWeight(newEdge.getWeight());
}
我不知道您在寻找什么,但是这种方法只是三行代码。从我的角度来看很简单。 我写了一个小例子来更好地说明这个想法:
Jedi obiwan = new Jedi(\"Obiwan\",30,40); // name,age and power
Jedi luke = new Jedi(\"Luke\",18,25);
Jedi mace = new Jedi(\"Mace-Windu\",100,450);
Jedi yoda = new Jedi(\"Yoda\",150,1000);

Jedi obiAgain = new Jedi(\"Obiwan\",11,40);

Set<Jedi> jedis = new HashSet<Jedi>(asList(obiwan,luke,mace,yoda));

if (!jedis.add(obiAgain)) {
     with(jedis).first(is(obiAgain)).updatePower(obiAgain.getPower());
}

System.out.println(jedis);