Skip to content

Commit 5d588a7

Browse files
committed
wip
1 parent 1a77ac1 commit 5d588a7

File tree

1 file changed

+89
-113
lines changed
  • core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation

1 file changed

+89
-113
lines changed

core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/ArrayBindingSet.java

+89-113
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,11 @@
1010
*******************************************************************************/
1111
package org.eclipse.rdf4j.query.algebra.evaluation;
1212

13-
import java.util.AbstractSet;
1413
import java.util.ArrayList;
1514
import java.util.Arrays;
16-
import java.util.Collection;
1715
import java.util.Collections;
18-
import java.util.ConcurrentModificationException;
1916
import java.util.Iterator;
17+
import java.util.LinkedHashSet;
2018
import java.util.List;
2119
import java.util.NoSuchElementException;
2220
import java.util.Set;
@@ -83,6 +81,7 @@ public ArrayBindingSet(BindingSet toCopy, Set<String> names, String[] namesArray
8381
}
8482
}
8583
this.empty = toCopy.isEmpty();
84+
assert !this.empty || size() == 0;
8685

8786
}
8887

@@ -93,6 +92,7 @@ public ArrayBindingSet(ArrayBindingSet toCopy, String... names) {
9392
this.whichBindingsHaveBeenSet = Arrays.copyOf(toCopy.whichBindingsHaveBeenSet,
9493
toCopy.whichBindingsHaveBeenSet.length);
9594
this.empty = toCopy.empty;
95+
assert !this.empty || size() == 0;
9696
}
9797

9898
/**
@@ -185,21 +185,30 @@ private int getIndex(String bindingName) {
185185

186186
@Override
187187
public Set<String> getBindingNames() {
188-
final int size = ArrayBindingSet.this.size();
189-
switch (size) {
190-
case 0:
191-
return Collections.emptySet();
192-
case 1:
193-
for (int i = 0; i < this.bindingNames.length; i++) {
194-
if (whichBindingsHaveBeenSet[i]) {
195-
return Collections.singleton(bindingNames[i]);
188+
if (bindingNamesSetCache == null) {
189+
int size = size();
190+
if (size == 0) {
191+
this.bindingNamesSetCache = Collections.emptySet();
192+
} else if (size == 1) {
193+
for (int i = 0; i < this.bindingNames.length; i++) {
194+
if (whichBindingsHaveBeenSet[i]) {
195+
this.bindingNamesSetCache = Collections.singleton(bindingNames[i]);
196+
break;
197+
}
198+
}
199+
assert this.bindingNamesSetCache != null;
200+
} else {
201+
LinkedHashSet<String> bindingNamesSetCache = new LinkedHashSet<>(size * 2);
202+
for (int i = 0; i < this.bindingNames.length; i++) {
203+
if (whichBindingsHaveBeenSet[i]) {
204+
bindingNamesSetCache.add(bindingNames[i]);
205+
}
196206
}
207+
this.bindingNamesSetCache = Collections.unmodifiableSet(bindingNamesSetCache);
197208
}
198-
throw new ConcurrentModificationException(
199-
"An bindingset has been modified during the getBindingNames call");
200-
default:
201-
return new MinimallyAllocatingSet(size);
202209
}
210+
211+
return bindingNamesSetCache;
203212
}
204213

205214
@Override
@@ -245,7 +254,7 @@ public Iterator<Binding> iterator() {
245254

246255
@Override
247256
public int size() {
248-
if (empty) {
257+
if (isEmpty()) {
249258
return 0;
250259
}
251260
int size = 0;
@@ -286,102 +295,6 @@ public List<String> getSortedBindingNames() {
286295
return sortedBindingNames;
287296
}
288297

289-
/*------------------------------------*
290-
* Inner class ArrayBindingSetIterator *
291-
*------------------------------------*/
292-
private static final class BindingToBindingNameIterator implements Iterator<String> {
293-
private final Iterator<Binding> nested;
294-
295-
private BindingToBindingNameIterator(Iterator<Binding> nested) {
296-
this.nested = nested;
297-
}
298-
299-
@Override
300-
public boolean hasNext() {
301-
return nested.hasNext();
302-
}
303-
304-
@Override
305-
public String next() {
306-
return nested.next().getName();
307-
}
308-
}
309-
310-
private final class MinimallyAllocatingSet extends AbstractSet<String> {
311-
312-
private final int size;
313-
314-
private MinimallyAllocatingSet(int size) {
315-
this.size = size;
316-
}
317-
318-
@Override
319-
public int size() {
320-
return size;
321-
}
322-
323-
@Override
324-
public Iterator<String> iterator() {
325-
Iterator<Binding> nested = ArrayBindingSet.this.iterator();
326-
return new BindingToBindingNameIterator(nested);
327-
}
328-
329-
@Override
330-
public boolean add(String e) {
331-
throw new UnsupportedOperationException();
332-
}
333-
334-
@Override
335-
public boolean addAll(Collection<? extends String> c) {
336-
throw new UnsupportedOperationException();
337-
}
338-
}
339-
340-
private class ArrayBindingSetIterator implements Iterator<Binding> {
341-
342-
private int index = 0;
343-
344-
public ArrayBindingSetIterator() {
345-
}
346-
347-
@Override
348-
public boolean hasNext() {
349-
// If the current index is at at a set value then this wont advance again.
350-
for (; index < values.length; index++) {
351-
if (whichBindingsHaveBeenSet[index] && values[index] != null) {
352-
return true;
353-
}
354-
}
355-
return false;
356-
}
357-
358-
@Override
359-
public Binding next() {
360-
for (; index < values.length; index++) {
361-
if (whichBindingsHaveBeenSet[index] && values[index] != null) {
362-
break;
363-
}
364-
}
365-
366-
try {
367-
String name = bindingNames[index];
368-
Value value = values[index++];
369-
if (value != null) {
370-
return new SimpleBinding(name, value);
371-
} else {
372-
return null;
373-
}
374-
} catch (ArrayIndexOutOfBoundsException e) {
375-
throw new NoSuchElementException();
376-
}
377-
}
378-
379-
@Override
380-
public void remove() {
381-
throw new UnsupportedOperationException();
382-
}
383-
}
384-
385298
@Override
386299
public void addBinding(Binding binding) {
387300
int index = getIndex(binding.getName());
@@ -393,9 +306,11 @@ public void addBinding(Binding binding) {
393306
return;
394307
}
395308

396-
assert !this.whichBindingsHaveBeenSet[index] : "variable already bound: " + binding.getName();
309+
assert !this.whichBindingsHaveBeenSet[index];
397310
this.values[index] = binding.getValue();
398311
this.whichBindingsHaveBeenSet[index] = true;
312+
empty = false;
313+
clearCache();
399314
}
400315

401316
@Override
@@ -406,6 +321,8 @@ public void setBinding(Binding binding) {
406321
}
407322
this.values[index] = binding.getValue();
408323
this.whichBindingsHaveBeenSet[index] = true;
324+
empty = false;
325+
clearCache();
409326
}
410327

411328
@Override
@@ -425,12 +342,29 @@ public void setBinding(String name, Value value) {
425342
break;
426343
}
427344
}
345+
} else {
346+
this.empty = false;
428347
}
429348
clearCache();
430349
}
431350

432351
@Override
433352
public boolean isEmpty() {
353+
if (empty) {
354+
for (boolean b : whichBindingsHaveBeenSet) {
355+
if (b) {
356+
assert false : "empty should be false";
357+
}
358+
}
359+
} else {
360+
var tempEmpty = true;
361+
for (boolean b : whichBindingsHaveBeenSet) {
362+
if (b) {
363+
tempEmpty = false;
364+
}
365+
}
366+
assert tempEmpty == empty;
367+
}
434368
return empty;
435369
}
436370

@@ -461,4 +395,46 @@ public void addAll(ArrayBindingSet other) {
461395

462396
}
463397

398+
private class ArrayBindingSetIterator implements Iterator<Binding> {
399+
400+
private int index = 0;
401+
402+
public ArrayBindingSetIterator() {
403+
}
404+
405+
@Override
406+
public boolean hasNext() {
407+
while (index < values.length) {
408+
if (whichBindingsHaveBeenSet[index]) {
409+
return true;
410+
}
411+
index++;
412+
}
413+
return false;
414+
}
415+
416+
@Override
417+
public Binding next() {
418+
while (index < values.length) {
419+
if (whichBindingsHaveBeenSet[index]) {
420+
String name = bindingNames[index];
421+
Value value = values[index++];
422+
if (value != null) {
423+
return new SimpleBinding(name, value);
424+
} else {
425+
return null;
426+
}
427+
}
428+
index++;
429+
}
430+
431+
throw new NoSuchElementException();
432+
}
433+
434+
@Override
435+
public void remove() {
436+
throw new UnsupportedOperationException();
437+
}
438+
}
439+
464440
}

0 commit comments

Comments
 (0)