Skip to content

Commit

Permalink
HSEARCH-2510 Avoid the extra iterable instantiation in CollectionHelp…
Browse files Browse the repository at this point in the history
…er.iteratorFromArray

Because there will be someone who's not happy with that extra
instantiation, I'm sure.

Calls to array accessors seem to be inlined, so there shouldn't be much
execution overhead.
  • Loading branch information
yrodiere authored and gsmet committed Jan 4, 2017
1 parent 2500692 commit 1b3c001
Showing 1 changed file with 130 additions and 170 deletions.
300 changes: 130 additions & 170 deletions engine/src/main/java/org/hibernate/search/util/impl/CollectionHelper.java
Expand Up @@ -91,8 +91,9 @@ else if ( names.length == 1 ) {
* @param object a given array
* @return an {@code Iterator} iterating over the array
*/
@SuppressWarnings({ "unchecked", "rawtypes" }) // Reflection is used to ensure the correct types are used
public static Iterator<?> iteratorFromArray(Object object) {
return iterableFromArray( object ).iterator();
return new ArrayIterator( accessorFromArray( object ), object );
}

/**
Expand All @@ -101,237 +102,196 @@ public static Iterator<?> iteratorFromArray(Object object) {
* @param object a given array
* @return an {@code Iterable} providing iterators over the array
*/
@SuppressWarnings({ "unchecked", "rawtypes" }) // Reflection is used to ensure the correct types are used
public static Iterable<?> iterableFromArray(Object object) {
Iterable<?> iterable;
return new ArrayIterable( accessorFromArray( object ), object );
}

private static ArrayAccessor<?, ?> accessorFromArray(Object object) {
ArrayAccessor<?, ?> accessor;
if ( Object.class.isAssignableFrom( object.getClass().getComponentType() ) ) {
iterable = new ObjectArrayIterable( (Object[]) object );
accessor = ArrayAccessor.OBJECT;
}
else if ( object.getClass() == boolean[].class ) {
iterable = new BooleanArrayIterable( (boolean[]) object );
accessor = ArrayAccessor.BOOLEAN;
}
else if ( object.getClass() == int[].class ) {
iterable = new IntArrayIterable( (int[]) object );
accessor = ArrayAccessor.INT;
}
else if ( object.getClass() == long[].class ) {
iterable = new LongArrayIterable( (long[]) object );
accessor = ArrayAccessor.LONG;
}
else if ( object.getClass() == double[].class ) {
iterable = new DoubleArrayIterable( (double[]) object );
accessor = ArrayAccessor.DOUBLE;
}
else if ( object.getClass() == float[].class ) {
iterable = new FloatArrayIterable( (float[]) object );
accessor = ArrayAccessor.FLOAT;
}
else if ( object.getClass() == byte[].class ) {
iterable = new ByteArrayIterable( (byte[]) object );
accessor = ArrayAccessor.BYTE;
}
else if ( object.getClass() == short[].class ) {
iterable = new ShortArrayIterable( (short[]) object );
accessor = ArrayAccessor.SHORT;
}
else if ( object.getClass() == char[].class ) {
iterable = new CharArrayIterable( (char[]) object );
accessor = ArrayAccessor.CHAR;
}
else {
throw new IllegalArgumentException( "Provided object " + object + " is not a supported array type" );
}
return iterable;
return accessor;
}

private abstract static class ArrayIterable<T> implements Iterable<T> {

protected abstract int size();

protected abstract T get(int index);

@Override
public final Iterator<T> iterator() {
return new ArrayIterator();
}

private class ArrayIterator implements Iterator<T> {
private int current = 0;

@Override
public boolean hasNext() {
return current < size();
}

@Override
public T next() {
T result = get( current );
current++;
return result;
}
}
}

private static class ObjectArrayIterable extends ArrayIterable<Object> {

private Object[] values;

private ObjectArrayIterable(Object[] values) {
this.values = values;
}

@Override
protected int size() {
return values.length;
}

@Override
protected Object get(int index) {
return values[index];
}
}

private static class BooleanArrayIterable extends ArrayIterable<Boolean> {

private boolean[] values;
private static class ArrayIterable<A, T> implements Iterable<T> {
private final ArrayAccessor<A, T> accessor;
private final A values;

private BooleanArrayIterable(boolean[] values) {
public ArrayIterable(ArrayAccessor<A, T> accessor, A values) {
this.accessor = accessor;
this.values = values;
}

@Override
protected int size() {
return values.length;
}

@Override
protected Boolean get(int index) {
return values[index];
}
}

private static class IntArrayIterable extends ArrayIterable<Integer> {

private int[] values;

private IntArrayIterable(int[] values) {
this.values = values;
}

@Override
protected int size() {
return values.length;
}

@Override
protected Integer get(int index) {
return values[index];
public final Iterator<T> iterator() {
return new ArrayIterator<>( accessor, values );
}
}

private static class LongArrayIterable extends ArrayIterable<Long> {

private long[] values;
private static class ArrayIterator<A, T> implements Iterator<T> {
private final ArrayAccessor<A, T> accessor;
private final A values;
private int current = 0;

private LongArrayIterable(long[] values) {
public ArrayIterator(ArrayAccessor<A, T> accessor, A values) {
this.accessor = accessor;
this.values = values;
}

@Override
protected int size() {
return values.length;
public boolean hasNext() {
return current < accessor.size( values );
}

@Override
protected Long get(int index) {
return values[index];
public T next() {
T result = accessor.get( values, current );
current++;
return result;
}
}

private static class DoubleArrayIterable extends ArrayIterable<Double> {
private interface ArrayAccessor<A, T> {

private double[] values;

private DoubleArrayIterable(double[] values) {
this.values = values;
}
int size(A array);

@Override
protected int size() {
return values.length;
}
T get(A array, int index);

@Override
protected Double get(int index) {
return values[index];
}
}

private static class FloatArrayIterable extends ArrayIterable<Float> {

private float[] values;

private FloatArrayIterable(float[] values) {
this.values = values;
}
ArrayAccessor<Object[], Object> OBJECT = new ArrayAccessor<Object[], Object>() {
@Override
public int size(Object[] array) {
return array.length;
}

@Override
protected int size() {
return values.length;
}
@Override
public Object get(Object[] array, int index) {
return array[index];
}
};

@Override
protected Float get(int index) {
return values[index];
}
}
ArrayAccessor<boolean[], Boolean> BOOLEAN = new ArrayAccessor<boolean[], Boolean>() {
@Override
public int size(boolean[] array) {
return array.length;
}

private static class ByteArrayIterable extends ArrayIterable<Byte> {
@Override
public Boolean get(boolean[] array, int index) {
return array[index];
}
};

private byte[] values;
ArrayAccessor<int[], Integer> INT = new ArrayAccessor<int[], Integer>() {
@Override
public int size(int[] array) {
return array.length;
}

private ByteArrayIterable(byte[] values) {
this.values = values;
}
@Override
public Integer get(int[] array, int index) {
return array[index];
}
};

@Override
protected int size() {
return values.length;
}
ArrayAccessor<long[], Long> LONG = new ArrayAccessor<long[], Long>() {
@Override
public int size(long[] array) {
return array.length;
}

@Override
protected Byte get(int index) {
return values[index];
}
}
@Override
public Long get(long[] array, int index) {
return array[index];
}
};

private static class ShortArrayIterable extends ArrayIterable<Short> {
ArrayAccessor<double[], Double> DOUBLE = new ArrayAccessor<double[], Double>() {
@Override
public int size(double[] array) {
return array.length;
}

private short[] values;
@Override
public Double get(double[] array, int index) {
return array[index];
}
};

private ShortArrayIterable(short[] values) {
this.values = values;
}
ArrayAccessor<float[], Float> FLOAT = new ArrayAccessor<float[], Float>() {
@Override
public int size(float[] array) {
return array.length;
}

@Override
protected int size() {
return values.length;
}
@Override
public Float get(float[] array, int index) {
return array[index];
}
};

@Override
protected Short get(int index) {
return values[index];
}
}
ArrayAccessor<byte[], Byte> BYTE = new ArrayAccessor<byte[], Byte>() {
@Override
public int size(byte[] array) {
return array.length;
}

private static class CharArrayIterable extends ArrayIterable<Character> {
@Override
public Byte get(byte[] array, int index) {
return array[index];
}
};

private char[] values;
ArrayAccessor<short[], Short> SHORT = new ArrayAccessor<short[], Short>() {
@Override
public int size(short[] array) {
return array.length;
}

private CharArrayIterable(char[] values) {
this.values = values;
}
@Override
public Short get(short[] array, int index) {
return array[index];
}
};

@Override
protected int size() {
return values.length;
}
ArrayAccessor<char[], Character> CHAR = new ArrayAccessor<char[], Character>() {
@Override
public int size(char[] array) {
return array.length;
}

@Override
protected Character get(int index) {
return values[index];
}
@Override
public Character get(char[] array, int index) {
return array[index];
}
};
}
}

0 comments on commit 1b3c001

Please sign in to comment.