blob: 8baf5553712c74ce5fe37cd3731c0ecce8366713 [file] [log] [blame]
/*
* 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();
}
};
}
}