Java 这看起来像是在图(JGrapthT)中查找没有传出边的顶点的有效方法吗?

Java 这看起来像是在图(JGrapthT)中查找没有传出边的顶点的有效方法吗?,java,graph,jgrapht,Java,Graph,Jgrapht,我使用JGraphT在内存图中保存大约150000个(或大约150000个)顶点。这是一个有向图,每个顶点都有{0 | 1}条出射边 我想找到并检索没有传出边的顶点集。以下是我的尝试: import io.vavr.Tuple; import io.vavr.Tuple2; import io.vavr.Tuple3; import io.vavr.control.Option; import org.jgrapht.Graphs; import org.jgrapht.graph.Simple

我使用JGraphT在内存图中保存大约150000个(或大约150000个)顶点。这是一个有向图,每个顶点都有{0 | 1}条出射边

我想找到并检索没有传出边的顶点集。以下是我的尝试:

import io.vavr.Tuple;
import io.vavr.Tuple2;
import io.vavr.Tuple3;
import io.vavr.control.Option;
import org.jgrapht.Graphs;
import org.jgrapht.graph.SimpleDirectedGraph;
import org.jgrapht.graph.concurrent.AsSynchronizedGraph;

 public Option<io.vavr.collection.Set<Employee>> 
 pickEmployeesWithNoSupervisor(Integer companyID) {
        
       // holdingCompany is of type: SimpleDirectedGraph<Employee,String>
       // edge is a simple string: "reportingTo"
       // Retrieve from a Map, initialized earlier, elsewhere

       var holdingCompany = this.allCompanies.get(companyID);
       if (holdingCompany == null)
                    return (Option.none());
       else {
        
           var vertices = holdingCompany.vertexSet();
           io.vavr.collection.Set<Employee> accumulator = io.vavr.collection.HashSet.empty();
           var allNoReportingToEmployees = 
                io.vavr.collection.HashSet.ofAll(vertices)
                .foldLeft(accumulator,(accu,nextEmp) -> {
                   var hasPredecessors = 
                          Graphs.vertexHasPredecessors(mayBeAKnownCompany,nextEmp);
                   return (!hasPredecessors ? accu.add(nextEmp) : accu) ;
                });
                   
            return Option.some(allNoReportingToEmployees);
          }
     }

     public class Employee {
        private final Integer empID;
      
        public Employee(Integer empID) {
            this.empID = empID;
        }

        @Override
        public boolean equals(Object o) {
           // ..
        }

        @Override
        public int hashCode() {
            // ..
        }
    }
导入io.vavr.Tuple;
导入io.vavr.Tuple2;
导入io.vavr.Tuple3;
导入io.vavr.control.Option;
导入org.jgrapht.Graphs;
导入org.jgrapht.graph.SimpleDirectedGraph;
导入org.jgrapht.graph.concurrent.AsSynchronizedGraph;
公共选择权
pickEmployeesWithNoSupervisor(整数公司ID){
//holdingCompany的类型为:SimpleDirectedGraph
//edge是一个简单的字符串:“reportingTo”
//从较早初始化的映射检索其他位置
var holdingCompany=this.allcompanys.get(companyID);
if(holdingCompany==null)
返回(Option.none());
否则{
var vertexts=holdingCompany.vertexSet();
io.vavr.collection.Set acculator=io.vavr.collection.HashSet.empty();
var ALLNOREPORTINGTO员工=
io.vavr.collection.HashSet.ofAll(顶点)
.foldLeft(蓄能器,(累计,下一温度)->{
var=
图.垂直排气分离器(Maybaknowncompany,nextEmp);
返回(!hasPreventors?累计添加(nextEmp):累计);
});
返回选项。部分(全部不向员工报告);
}
}
公营雇员{
私有最终整数empID;
公共雇员(整数empID){
this.empID=empID;
}
@凌驾
公共布尔等于(对象o){
// ..
}
@凌驾
公共int hashCode(){
// ..
}
}

这也许是一种幼稚的尝试。我很想知道是否有更好、更惯用、更高效的方法来实现这一点。

我不太确定代码中发生了什么,但下面的方法很好:

Set<Employee> verticesWithoutSucc = myGraph.vertexSet().stream().filter(v -> !Graphs.vertexHasSuccessors(myGraph,v)).collect(Collectors.toSet());
Set verticesWithoutSucc=myGraph.vertexSet().stream().filter(v->!Graphs.vertextsaccessors(myGraph,v)).collect(collector.toSet());
请注意,若要获取所有没有传出圆弧的顶点,必须使用
顶点排气分配器(.)
,而不是
顶点排气分配器(.)

请注意,
vertexhassaccessors
方法只是调用
!graph.outgoingEdgesOf(顶点).isEmpty()

这种方法应该是有效的,因为它在
O(n)
时间内运行,其中
n
是客户数。如果您想要更好的性能,可以在构建图的过程中跟踪所有顶点,而无需向外弧。也就是说,在图形中保留一组所有顶点,每次添加弧
(i,j)
,从集合中删除顶点
i
。因此,始终可以在固定时间内查询顶点集,而无需输出弧


最后,对于大型图,您可以查看
jgrapht opt
包中的优化图实现。

与您的代码相比,我的代码太冗长了!:-)我正试图实现同样的目标,是的,您的代码也告诉我,对于类似的任务,通常的方法应该是什么。谢谢让我把它合并到我的代码库中。还要感谢你指出继承者和前任之间的区别。当我直接在软件的页面上写代码时,我把事情搞砸了。再次感谢@乔里斯·金纳布尔