DegreeDistribution { @Procedure public Stream<DegreeStats.Result> degrees(@Name(value = "types", defaultValue = "") String types) { List<DegreeStats> stats = prepareStats(types); MultiThreadedGlobalGraphOperations.forAllNodes(db, pools.getDefaultExecutorService(), BATCHSIZE, (ktx,nodeCursor)-> stats.forEach((s) -> s.computeDegree(nodeCursor, ktx.cursors())) ); return stats.stream().map(DegreeStats::done); }  @Procedure Stream<DegreeStats.Result> degrees(@Name(value = "types", defaultValue = "") String types); List<DegreeStats> prepareStats(String types); @Context
    public GraphDatabaseAPI db; @Context
    public KernelTransaction tx; @Context
    public Pools pools; }
@Test public void degrees() throws Exception { TestUtil.testCall(db, "CALL apoc.stats.degrees()", row -> { assertEquals(null,row.get("type")); assertEquals("BOTH",row.get("direction")); assertEquals(55L,row.get("total")); assertEquals(10L,row.get("max")); assertEquals(1L,row.get("min")); assertEquals(5.5d,row.get("mean")); assertEquals(10L,row.get("p99")); assertEquals(5L,row.get("p50")); }); TestUtil.testCall(db, "CALL apoc.stats.degrees('BAR>')", row -> { assertEquals("BAR",row.get("type")); assertEquals("OUTGOING",row.get("direction")); assertEquals(55L,row.get("total")); assertEquals(10L,row.get("max")); assertEquals(1L,row.get("min")); assertEquals(5.5d,row.get("mean")); assertEquals(10L,row.get("p99")); assertEquals(5L,row.get("p50")); }); }