Skip to content

Commit 63dc531

Browse files
authored
Implement spliterator for both nodes and edges (#240)
* Implement spliterator for both nodes and edges, while keeping fallback on iterator() * Locking on toArray, toCollection and toSet for wrappers and parallel * Optimise imports * Set version to 0.8.0-SNAPSHOT * Fix sizing issue with node's spliterator and create custom one for graph view * Also fix edge spliterator, introducing both SIZED and non SIZED options * Set default node block to 8192 * Improve unit tests for ede spliterator
1 parent c2bbee6 commit 63dc531

25 files changed

+1350
-232
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<modelVersion>4.0.0</modelVersion>
44
<groupId>org.gephi</groupId>
55
<artifactId>graphstore</artifactId>
6-
<version>0.7.4-SNAPSHOT</version>
6+
<version>0.8.0-SNAPSHOT</version>
77
<packaging>jar</packaging>
88

99
<name>GraphStore</name>

src/main/java/org/gephi/graph/api/EdgeIterable.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import java.util.Iterator;
2121
import java.util.NoSuchElementException;
2222
import java.util.Set;
23+
import java.util.Spliterator;
24+
import java.util.Spliterators;
2325

2426
/**
2527
* An edge iterable.
@@ -63,10 +65,24 @@ public interface EdgeIterable extends ElementIterable<Edge> {
6365
@Override
6466
public Set<Edge> toSet();
6567

68+
/**
69+
* Returns a Spliterator over the edges.
70+
* <p>
71+
* Implementations return a splittable, sized, fail-fast spliterator suitable
72+
* for parallel streams. When not possible, a non-splittable spliterator is
73+
* returned.
74+
*
75+
* @return edge spliterator
76+
*/
77+
@Override
78+
default Spliterator<Edge> spliterator() {
79+
return ElementIterable.super.spliterator();
80+
}
81+
6682
/**
6783
* Empty edge iterable.
6884
*/
69-
static final class EdgeIterableEmpty implements Iterator<Edge>, EdgeIterable {
85+
final class EdgeIterableEmpty implements Iterator<Edge>, EdgeIterable {
7086

7187
@Override
7288
public boolean hasNext() {
@@ -88,6 +104,11 @@ public Iterator<Edge> iterator() {
88104
return this;
89105
}
90106

107+
@Override
108+
public Spliterator<Edge> spliterator() {
109+
return Spliterators.emptySpliterator();
110+
}
111+
91112
@Override
92113
public Edge[] toArray() {
93114
return new Edge[0];

src/main/java/org/gephi/graph/api/ElementIterable.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020
import java.util.Iterator;
2121
import java.util.NoSuchElementException;
2222
import java.util.Set;
23+
import java.util.Spliterator;
24+
import java.util.Spliterators;
25+
import java.util.stream.Stream;
26+
import java.util.stream.StreamSupport;
2327

2428
/**
2529
* Element iterable.
@@ -41,6 +45,25 @@ public interface ElementIterable<T extends Element> extends Iterable<T> {
4145
@Override
4246
public Iterator<T> iterator();
4347

48+
/**
49+
* Creates a new sequential stream, based on the spliterator returned.
50+
*
51+
* @return stream
52+
*/
53+
default Stream<T> stream() {
54+
return StreamSupport.stream(spliterator(), false);
55+
}
56+
57+
/**
58+
* Creates a new sequential and parallel stream, based on the spliterator
59+
* returned.
60+
*
61+
* @return stream
62+
*/
63+
default Stream<T> parallelStream() {
64+
return StreamSupport.stream(spliterator(), true);
65+
}
66+
4467
/**
4568
* Returns the iterator content as an array.
4669
*
@@ -92,6 +115,11 @@ public Iterator<Element> iterator() {
92115
return this;
93116
}
94117

118+
@Override
119+
public Spliterator<Element> spliterator() {
120+
return Spliterators.emptySpliterator();
121+
}
122+
95123
@Override
96124
public Element[] toArray() {
97125
return new Node[0];

src/main/java/org/gephi/graph/api/NodeIterable.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import java.util.Iterator;
2121
import java.util.NoSuchElementException;
2222
import java.util.Set;
23+
import java.util.Spliterator;
24+
import java.util.Spliterators;
2325

2426
/**
2527
* A node iterable.
@@ -63,6 +65,20 @@ public interface NodeIterable extends ElementIterable<Node> {
6365
@Override
6466
public Set<Node> toSet();
6567

68+
/**
69+
* Returns a Spliterator over the nodes.
70+
* <p>
71+
* Implementations return a splittable, sized, fail-fast spliterator suitable
72+
* for parallel streams. When not possible, a non-splittable spliterator is
73+
* returned.
74+
*
75+
* @return node spliterator
76+
*/
77+
@Override
78+
default Spliterator<Node> spliterator() {
79+
return ElementIterable.super.spliterator();
80+
}
81+
6682
/**
6783
* Empty node iterable.
6884
*/
@@ -88,6 +104,11 @@ public Iterator<Node> iterator() {
88104
return this;
89105
}
90106

107+
@Override
108+
public Spliterator<Node> spliterator() {
109+
return Spliterators.emptySpliterator();
110+
}
111+
91112
@Override
92113
public Node[] toArray() {
93114
return new Node[0];

src/main/java/org/gephi/graph/impl/ColumnObserverImpl.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import cern.colt.bitvector.QuickBitVector;
2020
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
2121
import it.unimi.dsi.fastutil.objects.ObjectList;
22+
import it.unimi.dsi.fastutil.objects.ObjectLists;
2223
import org.gephi.graph.api.AttributeUtils;
2324
import org.gephi.graph.api.Column;
2425
import org.gephi.graph.api.ColumnDiff;
@@ -155,7 +156,8 @@ protected final class NodeColumnDiffImpl extends ColumnDiffImpl<Node> {
155156
@Override
156157
public NodeIterable getTouchedElements() {
157158
if (!touchedElements.isEmpty()) {
158-
return graphStore.getNodeIterableWrapper(touchedElements.iterator(), false);
159+
return new NodeIterableWrapper(() -> ObjectLists.unmodifiable(touchedElements).iterator(),
160+
() -> ObjectLists.unmodifiable(touchedElements).spliterator(), null);
159161

160162
}
161163
return NodeIterable.NodeIterableEmpty.EMPTY;
@@ -167,8 +169,8 @@ protected final class EdgeColumnDiffImpl extends ColumnDiffImpl<Edge> {
167169
@Override
168170
public EdgeIterable getTouchedElements() {
169171
if (!touchedElements.isEmpty()) {
170-
return graphStore.getEdgeIterableWrapper(touchedElements.iterator(), false);
171-
172+
return new EdgeIterableWrapper(() -> ObjectLists.unmodifiable(touchedElements).iterator(),
173+
() -> ObjectLists.unmodifiable(touchedElements).spliterator(), null);
172174
}
173175
return EdgeIterable.EdgeIterableEmpty.EMPTY;
174176
}

src/main/java/org/gephi/graph/impl/EdgeIterableWrapper.java

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,32 @@
1616
package org.gephi.graph.impl;
1717

1818
import java.util.Iterator;
19+
import java.util.Spliterator;
20+
import java.util.function.Supplier;
21+
import java.util.stream.StreamSupport;
1922
import org.gephi.graph.api.Edge;
2023
import org.gephi.graph.api.EdgeIterable;
2124

2225
public class EdgeIterableWrapper extends ElementIterableWrapper<Edge> implements EdgeIterable {
2326

24-
public EdgeIterableWrapper(Iterator<Edge> iterator) {
25-
super(iterator);
27+
public EdgeIterableWrapper(Supplier<Iterator<Edge>> iteratorSupplier, GraphLockImpl lock) {
28+
super(iteratorSupplier, lock);
2629
}
2730

28-
public EdgeIterableWrapper(Iterator<Edge> iterator, GraphLockImpl lock) {
29-
super(iterator, lock);
31+
public EdgeIterableWrapper(Supplier<Iterator<Edge>> iteratorSupplier, Supplier<Spliterator<Edge>> spliteratorSupplier, GraphLockImpl lock) {
32+
super(iteratorSupplier, spliteratorSupplier, lock);
3033
}
3134

3235
@Override
3336
public Edge[] toArray() {
34-
return toArray(new Edge[0]);
37+
if (parallelPossible && lock != null) {
38+
lock.readLock();
39+
try {
40+
return StreamSupport.stream(spliterator(), true).toArray(Edge[]::new);
41+
} finally {
42+
lock.readUnlock();
43+
}
44+
}
45+
return StreamSupport.stream(spliterator(), parallelPossible).toArray(Edge[]::new);
3546
}
3647
}

0 commit comments

Comments
 (0)