com.fitbur.jackson.databind.util.ArrayBuilders Maven / Gradle / Ivy
package com.fitbur.jackson.databind.util;
import java.lang.reflect.Array;
import java.util.*;
/**
* Helper class that contains set of distinct builders for different
* arrays of primitive values. It also provides trivially simple
* reuse scheme, which assumes that caller knows not to use instances
* concurrently (which works ok with primitive arrays since they can
* not contain other non-primitive types).
* Also note that instances are not thread safe; the intent is that
* a builder is constructed on per-call (deserialization) basis.
*/
public final class ArrayBuilders
{
private BooleanBuilder _booleanBuilder = null;
// note: no need for char[] builder, assume they are Strings
private ByteBuilder _byteBuilder = null;
private ShortBuilder _shortBuilder = null;
private IntBuilder _intBuilder = null;
private LongBuilder _longBuilder = null;
private FloatBuilder _floatBuilder = null;
private DoubleBuilder _doubleBuilder = null;
public ArrayBuilders() { }
public BooleanBuilder getBooleanBuilder()
{
if (_booleanBuilder == null) {
_booleanBuilder = new BooleanBuilder();
}
return _booleanBuilder;
}
public ByteBuilder getByteBuilder()
{
if (_byteBuilder == null) {
_byteBuilder = new ByteBuilder();
}
return _byteBuilder;
}
public ShortBuilder getShortBuilder()
{
if (_shortBuilder == null) {
_shortBuilder = new ShortBuilder();
}
return _shortBuilder;
}
public IntBuilder getIntBuilder()
{
if (_intBuilder == null) {
_intBuilder = new IntBuilder();
}
return _intBuilder;
}
public LongBuilder getLongBuilder()
{
if (_longBuilder == null) {
_longBuilder = new LongBuilder();
}
return _longBuilder;
}
public FloatBuilder getFloatBuilder()
{
if (_floatBuilder == null) {
_floatBuilder = new FloatBuilder();
}
return _floatBuilder;
}
public DoubleBuilder getDoubleBuilder()
{
if (_doubleBuilder == null) {
_doubleBuilder = new DoubleBuilder();
}
return _doubleBuilder;
}
/*
/**********************************************************
/* Impl classes
/**********************************************************
*/
public final static class BooleanBuilder
extends PrimitiveArrayBuilder
{
public BooleanBuilder() { }
@Override
public final boolean[] _constructArray(int len) { return new boolean[len]; }
}
public final static class ByteBuilder
extends PrimitiveArrayBuilder
{
public ByteBuilder() { }
@Override
public final byte[] _constructArray(int len) { return new byte[len]; }
}
public final static class ShortBuilder
extends PrimitiveArrayBuilder
{
public ShortBuilder() { }
@Override
public final short[] _constructArray(int len) { return new short[len]; }
}
public final static class IntBuilder
extends PrimitiveArrayBuilder
{
public IntBuilder() { }
@Override
public final int[] _constructArray(int len) { return new int[len]; }
}
public final static class LongBuilder
extends PrimitiveArrayBuilder
{
public LongBuilder() { }
@Override
public final long[] _constructArray(int len) { return new long[len]; }
}
public final static class FloatBuilder
extends PrimitiveArrayBuilder
{
public FloatBuilder() { }
@Override
public final float[] _constructArray(int len) { return new float[len]; }
}
public final static class DoubleBuilder
extends PrimitiveArrayBuilder
{
public DoubleBuilder() { }
@Override
public final double[] _constructArray(int len) { return new double[len]; }
}
/*
/**********************************************************
/* Static helper methods
/**********************************************************
*/
/**
* Helper method used for constructing simple value comparator used for
* comparing arrays for content equality.
*
* Note: current implementation is not optimized for speed; if performance
* ever becomes an issue, it is possible to construct much more efficient
* typed instances (one for Object[] and sub-types; one per primitive type).
*
* @since 2.2 Moved from earlier Comparators
class
*/
public static Object getArrayComparator(final Object defaultValue)
{
final int length = Array.getLength(defaultValue);
final Class> defaultValueType = defaultValue.getClass();
return new Object() {
@Override
public boolean equals(Object other) {
if (other == this) return true;
if (other == null || other.getClass() != defaultValueType) {
return false;
}
if (Array.getLength(other) != length) return false;
// so far so good: compare actual equality; but only shallow one
for (int i = 0; i < length; ++i) {
Object value1 = Array.get(defaultValue, i);
Object value2 = Array.get(other, i);
if (value1 == value2) continue;
if (value1 != null) {
if (!value1.equals(value2)) {
return false;
}
}
}
return true;
}
};
}
public static HashSet arrayToSet(T[] elements)
{
HashSet result = new HashSet();
if (elements != null) {
for (T elem : elements) {
result.add(elem);
}
}
return result;
}
public static ArrayList arrayToList(T[] elements)
{
ArrayList result = new ArrayList();
if (elements != null) {
for (T elem : elements) {
result.add(elem);
}
}
return result;
}
public static HashSet setAndArray(Set set, T[] elements)
{
HashSet result = new HashSet();
if (set != null) {
result.addAll(set);
}
if (elements != null) {
for (T value : elements) {
result.add(value);
}
}
return result;
}
/**
* Helper method for adding specified element to a List, but also
* considering case where the List may not have been yet constructed
* (that is, null is passed instead).
*
* @param list List to add to; may be null to indicate that a new
* List is to be constructed
* @param element Element to add to list
*
* @return List in which element was added; either list
* (if it was not null), or a newly constructed List.
*/
public static List addToList(List list, T element)
{
if (list == null) {
list = new ArrayList();
}
list.add(element);
return list;
}
/**
* Helper method for constructing a new array that contains specified
* element followed by contents of the given array. No checking is done
* to see if element being inserted is duplicate.
*/
public static T[] insertInList(T[] array, T element)
{
int len = array.length;
@SuppressWarnings("unchecked")
T[] result = (T[]) Array.newInstance(array.getClass().getComponentType(), len+1);
if (len > 0) {
System.arraycopy(array, 0, result, 1, len);
}
result[0] = element;
return result;
}
/**
* Helper method for constructing a new array that contains specified
* element followed by contents of the given array but never contains
* duplicates.
* If element already existed, one of two things happens: if the element
* was already the first one in array, array is returned as is; but
* if not, a new copy is created in which element has moved as the head.
*/
@SuppressWarnings("unchecked")
public static T[] insertInListNoDup(T[] array, T element)
{
final int len = array.length;
// First: see if the element already exists
for (int ix = 0; ix < len; ++ix) {
if (array[ix] == element) {
// if at head already, return as is
if (ix == 0) {
return array;
}
// otherwise move things around
T[] result = (T[]) Array.newInstance(array.getClass().getComponentType(), len);
System.arraycopy(array, 0, result, 1, ix);
result[0] = element;
++ix;
int left = len - ix;
if (left > 0) {
System.arraycopy(array, ix, result, ix, left);
}
return result;
}
}
// but if not, allocate new array, move
T[] result = (T[]) Array.newInstance(array.getClass().getComponentType(), len+1);
if (len > 0) {
System.arraycopy(array, 0, result, 1, len);
}
result[0] = element;
return result;
}
}