10
10
*******************************************************************************/
11
11
package org .eclipse .rdf4j .query .algebra .evaluation ;
12
12
13
- import java .util .AbstractSet ;
14
13
import java .util .ArrayList ;
15
14
import java .util .Arrays ;
16
- import java .util .Collection ;
17
15
import java .util .Collections ;
18
- import java .util .ConcurrentModificationException ;
19
16
import java .util .Iterator ;
17
+ import java .util .LinkedHashSet ;
20
18
import java .util .List ;
21
19
import java .util .NoSuchElementException ;
22
20
import java .util .Set ;
@@ -83,6 +81,7 @@ public ArrayBindingSet(BindingSet toCopy, Set<String> names, String[] namesArray
83
81
}
84
82
}
85
83
this .empty = toCopy .isEmpty ();
84
+ assert !this .empty || size () == 0 ;
86
85
87
86
}
88
87
@@ -93,6 +92,7 @@ public ArrayBindingSet(ArrayBindingSet toCopy, String... names) {
93
92
this .whichBindingsHaveBeenSet = Arrays .copyOf (toCopy .whichBindingsHaveBeenSet ,
94
93
toCopy .whichBindingsHaveBeenSet .length );
95
94
this .empty = toCopy .empty ;
95
+ assert !this .empty || size () == 0 ;
96
96
}
97
97
98
98
/**
@@ -185,21 +185,30 @@ private int getIndex(String bindingName) {
185
185
186
186
@ Override
187
187
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
+ }
196
206
}
207
+ this .bindingNamesSetCache = Collections .unmodifiableSet (bindingNamesSetCache );
197
208
}
198
- throw new ConcurrentModificationException (
199
- "An bindingset has been modified during the getBindingNames call" );
200
- default :
201
- return new MinimallyAllocatingSet (size );
202
209
}
210
+
211
+ return bindingNamesSetCache ;
203
212
}
204
213
205
214
@ Override
@@ -245,7 +254,7 @@ public Iterator<Binding> iterator() {
245
254
246
255
@ Override
247
256
public int size () {
248
- if (empty ) {
257
+ if (isEmpty () ) {
249
258
return 0 ;
250
259
}
251
260
int size = 0 ;
@@ -286,102 +295,6 @@ public List<String> getSortedBindingNames() {
286
295
return sortedBindingNames ;
287
296
}
288
297
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
-
385
298
@ Override
386
299
public void addBinding (Binding binding ) {
387
300
int index = getIndex (binding .getName ());
@@ -393,9 +306,11 @@ public void addBinding(Binding binding) {
393
306
return ;
394
307
}
395
308
396
- assert !this .whichBindingsHaveBeenSet [index ] : "variable already bound: " + binding . getName () ;
309
+ assert !this .whichBindingsHaveBeenSet [index ];
397
310
this .values [index ] = binding .getValue ();
398
311
this .whichBindingsHaveBeenSet [index ] = true ;
312
+ empty = false ;
313
+ clearCache ();
399
314
}
400
315
401
316
@ Override
@@ -406,6 +321,8 @@ public void setBinding(Binding binding) {
406
321
}
407
322
this .values [index ] = binding .getValue ();
408
323
this .whichBindingsHaveBeenSet [index ] = true ;
324
+ empty = false ;
325
+ clearCache ();
409
326
}
410
327
411
328
@ Override
@@ -425,12 +342,29 @@ public void setBinding(String name, Value value) {
425
342
break ;
426
343
}
427
344
}
345
+ } else {
346
+ this .empty = false ;
428
347
}
429
348
clearCache ();
430
349
}
431
350
432
351
@ Override
433
352
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
+ }
434
368
return empty ;
435
369
}
436
370
@@ -461,4 +395,46 @@ public void addAll(ArrayBindingSet other) {
461
395
462
396
}
463
397
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
+
464
440
}
0 commit comments