| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.jena.mem; |
| |
| import java.util.ConcurrentModificationException ; |
| |
| import org.apache.jena.graph.Triple ; |
| import org.apache.jena.util.iterator.ExtendedIterator ; |
| import org.apache.jena.util.iterator.NiceIterator ; |
| |
| /** |
| An ArrayBunch implements TripleBunch with a linear search of a short-ish |
| array of Triples. The array can grow, but it only grows by 4 elements each time |
| (because, if it gets big enough for this linear growth to be bad, it should anyways |
| have been replaced by a more efficient set-of-triples implementation). |
| */ |
| public class ArrayBunch implements TripleBunch |
| { |
| |
| protected int size = 0; |
| protected Triple [] elements; |
| protected volatile int changes = 0; |
| |
| public ArrayBunch() |
| { elements = new Triple[5]; } |
| |
| @Override |
| public boolean containsBySameValueAs( Triple t ) |
| { |
| int i = size; |
| while (i > 0) if (t.matches( elements[--i])) return true; |
| return false; |
| } |
| |
| @Override |
| public boolean contains( Triple t ) |
| { |
| int i = size; |
| while (i > 0) if (t.equals( elements[--i] )) return true; |
| return false; |
| } |
| |
| @Override |
| public int size() |
| { return size; } |
| |
| @Override |
| public void add( Triple t ) |
| { |
| if (size == elements.length) grow(); |
| elements[size++] = t; |
| changes += 1; |
| } |
| |
| /** |
| Note: linear growth is suboptimal (order n<sup>2</sup>) normally, but |
| ArrayBunch's are meant for <i>small</i> sets and are replaced by some |
| sort of hash- or tree- set when they get big; currently "big" means more |
| than 9 elements, so that's only one growth spurt anyway. |
| */ |
| protected void grow() |
| { |
| Triple [] newElements = new Triple[size + 4]; |
| System.arraycopy( elements, 0, newElements, 0, size ); |
| elements = newElements; |
| } |
| |
| @Override |
| public void remove( Triple t ) |
| { |
| changes += 1; |
| for (int i = 0; i < size; i += 1) |
| { |
| if (t.equals( elements[i] )) |
| { elements[i] = elements[--size]; |
| return; } |
| } |
| } |
| |
| @Override |
| public ExtendedIterator<Triple> iterator() |
| { |
| return iterator( new HashCommon.NotifyEmpty() { @Override |
| public void emptied() {} } ); |
| } |
| |
| @Override |
| public ExtendedIterator<Triple> iterator( final HashCommon.NotifyEmpty container ) |
| { |
| return new NiceIterator<Triple>() |
| { |
| protected final int initialChanges = changes; |
| |
| protected int i = size; |
| protected final Triple [] e = elements; |
| |
| @Override public boolean hasNext() |
| { |
| if (changes > initialChanges) throw new ConcurrentModificationException(); |
| return i > 0; |
| } |
| |
| @Override public Triple next() |
| { |
| if (changes > initialChanges) throw new ConcurrentModificationException(); |
| if (i == 0) noElements( "no elements left in ArrayBunch iteration" ); |
| return e[--i]; |
| } |
| |
| @Override public void remove() |
| { |
| if (changes > initialChanges) throw new ConcurrentModificationException(); |
| int last = --size; |
| e[i] = e[last]; |
| e[last] = null; |
| if (size == 0) container.emptied(); |
| } |
| }; |
| } |
| } |