Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Generic" solution for primitive array?

I have classes that for processing primitive array input: CharArrayExtractor for char[], ByteArrayExtractor for byte[], IntegerArrayExtractor for int[], ...

public void CharArrayExtractor {

    public List<Record> extract(char[] source) {
        List<Record> records = new ArrayList<Record>();
        int recordStartFlagPos = -1;
        int recordEndFlagPos = -1;
        for (int i = 0; i < source.length; i++) {
            if (source[i] == RECORD_START_FLAG) {
                recordStartFlagPos = i;
            } else if (source[i] == RECORD_END_FLAG) {
                recordEndFlagPos = i;
            }
            if (recordStartFlagPos != -1 && recordEndFlagPos != -1) {
                Record newRecord = makeRecord(source, recordStartFlagPos,
                        recordEndFlagPos);
                records.add(newRecord);
                recordStartFlagPos = -1;
                recordEngFlagPos = -1;
            }
        }
    }
}

public void ByteArrayExtractor {

    public List<Record> extract(byte[] source) {
        // filter and extract data from the array.
    }
}

public void IntegerArrayExtractor {

    public List<Record> extract(int[] source) {
        // filter and extract data from the array.
    }
}

The problem here is that the algorithm for extracting the data is the same, only the types of input are different. Everytime the algorithm changes, I have to change all of the extractor classes.

Is there a way to make extractor classes more "generics"?

Best regards.

EDIT: It seems that every suggestion so far is to use autoboxing to archive generic. But the number of elements of the array is often large, so I avoid using autoboxing.

I added more specific implementation of how the data is being extracted. Hope it will clarify something.

like image 830
Genzer Avatar asked Aug 12 '11 14:08

Genzer


People also ask

Can generics be used for primitive types?

Using generics, primitive types can not be passed as type parameters. In the example given below, if we pass int primitive type to box class, then compiler will complain. To mitigate the same, we need to pass the Integer object instead of int primitive type.

Can generic be used with array?

Java allows generic classes, methods, etc. that can be declared independent of types. However, Java does not allow the array to be generic. The reason for this is that in Java, arrays contain information related to their components and this information is used to allocate memory at runtime.

Can primitive types be used in generics Java?

To use Java generics effectively, you must consider the following restrictions: Cannot Instantiate Generic Types with Primitive Types. Cannot Create Instances of Type Parameters. Cannot Declare Static Fields Whose Types are Type Parameters.

What is generic array list?

The ArrayList class is similar to an array, but it automatically adjusts its capacity as you add and remove elements, without your needing to write any code. As of Java SE 5.0, ArrayList is a generic class with a type parameter.


2 Answers

New Idea

Or a different approach is wrapping the primitive arrays and covering them with the methods you use for your algorithm.

public PrimitiveArrayWrapper {
    private byte[] byteArray = null;
    private int[] intArray = null;
    ...

    public PrimitiveArrayWrapper(byte[] byteArray) {
        this.byteArray = byteArray;
    }

    // other constructors

    public String extractFoo1(String pattern) {
        if(byteArray != null) {
          // do action on byteArray
        } else if(....) 
        ...
    }
}

public class AlgorithmExtractor {
    public List<Record> do(PrimitiveArrayWrapper wrapper) {
        String  s= wrapper.extractFoo1("abcd");
        ...
    }
}

This mainly depends if you have a lot of methods to call which you would have to cover. but at least you must not edit the algorithm more over the way how to access the primitive array. Furthermor you would also be able to use a different object inside the wrapper.

Old Idea

Either use generics or what i also think about is to have three methods which convert the primitive types into value types.

public void Extractor {
    public List<Record> extract(byte[] data) {
        InternalExtractor<Byte> ie = new InternalExtractor<Byte>();
        return ie.internalExtract(ArrayUtils.toObject(data));
    }

    public List<Record> extract(int[] data) {
        ...
    }
}

public void InternalExtractor<T> {
    private List<Record> internalExtract(T[] data) {
        // do the extraction
    }
}

ArrayUtils is a helper class from commons lang from Apache.

like image 62
rit Avatar answered Sep 30 '22 02:09

rit


interface Source
    int length();
    int get(int index);

extract(final byte[] source)
    extract( new Source(){
        int length(){ return source.length; }
        int get(int i){ return source[i]; }
    } );

// common algorithm
extract(Source source)
    for(int i=0; i<source.lenth(); i++)
        int data = source.get(i);
        ...
like image 28
irreputable Avatar answered Sep 30 '22 02:09

irreputable