Link to home
Start Free TrialLog in
Avatar of ylyip
ylyip

asked on

Dynamic array of primitive types

Hi all,

I always encounter the situation to read an unknown number of primitive values, like int or float. I don't want to create wrapper objects and put them into ArrayList or Vector because it takes longer time and larger space. Is there any way to tackle the problem?

Thanks in advance.
Avatar of Igor Bazarny
Igor Bazarny
Flag of Switzerland image

Hi,

You can recreate ArrayList behaviour. Something like:

public class IntVector{
    private int[] content = new int[10];
    private int used = 0;

    public int get(int index){
        if(i<0 || i>=used){
             throw new ArrayIndexOutOfBoundsException("wrong index: "+index)
        }
        return content[i];
    }

    public void add(int i){
        if( used == content.length ){
            int[] expanded = new int[content.length*2];
            System.arraycopy(content,0,expanded,0,content.length);
            content = expanded;
        }
    }

    public int size(){
        return used;
    }
    // etc.
    // Take care of synchronization if you are going to use same instance from multiple threads.
}

Regards,
Igor Bazarny,
Brainbench MVP for Java 1
Avatar of ylyip
ylyip

ASKER

Thanks Bazarny, but is there a more generic solution? I mean this time if I need dynamic int array, I write one class, next time when I need dynamic float array, I write another one. Just another time I need a HashMap-like structure with int keys, another more complicated one. Do the standard packages of Java (perhaps in the new 1.4) contain any class for the purpose?
Hi,

I'm afraid there is no ready to use solution. Besides, I don't think you need something more complicated than array. HashMap would anyway need at least one object per entry, so wrapping primitive would not be a big performance hit. Besides, for ints you could cache, say, first 100 and reuse instances:

class IntWrapper{

Integer cache = new Integer[100];

public Integer wrap(int value){
    if(value <0 || value >= cache.length){
        return new Integer(value);
    }
    if( cache[value] == null ){
        cache[value] = new Integer(value);
    }
    return cache[value];
}

Regards,
Igor Bazarny
Avatar of ylyip

ASKER

Bazarny, thanks for your comment. I am dealing with very large datasets, with up to several hundred thousands of records and up to several thousands attributes per record. Therefore I need to save as much memory as possible, so caching does not seem feasible.
ASKER CERTIFIED SOLUTION
Avatar of Igor Bazarny
Igor Bazarny
Flag of Switzerland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hi,


There's an error and my source-code doesn't go in.. Email me at doronbarak@hotmail.com to get a source-code for a generic Argument class..


Doron
Hi,


Ok, I'll try posting in the code for the generic wrapper in chunks:

import java.lang.reflect.Array;

public class Argument {
     private Object array;
     private Class currentClass;

     private Argument(Class objClass) {
          array = null;
          currentClass = null;
          checkType(objClass);
     }

     private void checkType(Class objClass) {
          if (objClass != currentClass) {
               currentClass = objClass;
               array = Array.newInstance(currentClass, 1);
          }
     }

     public Object getValue() {
          return Array.get(array, 0);
     }

     public void setValue(Object value) {
          currentClass = null;          
          array = value;
     }

To be continued...
Ok, lets try the "setValue" part:

     public void setValue(boolean value) {
          checkType(boolean.class);
          Array.setBoolean(array, 0, value);
     }

     public void setValue(byte value) {
          checkType(byte.class);
          Array.setByte(array, 0, value);
     }

     public void setValue(char value) {
          checkType(char.class);
          Array.setChar(array, 0, value);
     }

     public void setValue(double value) {
          checkType(double.class);
          Array.setDouble(array, 0, value);
     }

     public void setValue(float value) {
          checkType(float.class);
          Array.setFloat(array, 0, value);
     }

     public void setValue(int value) {
          checkType(int.class);
          Array.setInt(array, 0, value);
     }

     public void setValue(long value) {
          checkType(long.class);
          Array.setLong(array, 0, value);
     }

     public void setValue(short value) {
          checkType(short.class);
          Array.setShort(array, 0, value);
     }

To be continued...
Ok, now the "getXXXX" part:

     public static char getChar(Object obj) {
          return ((Character)getObject(obj)).charValue();
     }

     public static boolean getBoolean(Object obj) {
          return ((Boolean)getObject(obj)).booleanValue();
     }

     public static byte getByte(Object obj) {
          return ((Byte)getObject(obj)).byteValue();
     }

     public static double getDouble(Object obj) {
          return ((Double)getObject(obj)).doubleValue();
     }

     public static float getFloat(Object obj) {
          return ((Float)getObject(obj)).floatValue();
     }

     public static int getInteger(Object obj) {
          return ((Integer)getObject(obj)).intValue();
     }

     public static long getLong(Object obj) {
          return ((Long)getObject(obj)).longValue();
     }

     public static short getShort(Object obj) {
          return ((Short)getObject(obj)).shortValue();
     }

     public static Object getObject(Object obj) {
          return (obj instanceof Argument) ? ((Argument)obj).getValue() : obj;
     }

To be continued...
Last part:

     public static Argument set(boolean value) {
          Argument o = new Argument(boolean.class);
          o.setValue(value);
          return o;
     }

     public static Argument set(byte value) {
          Argument o = new Argument(byte.class);
          o.setValue(value);
          return o;
     }

     public static Argument set(char value) {
          Object o = new Argument(char.class);
          o.setValue(value);
          return o;
     }

     public static Argument set(double value) {
          Argument o = new Argument(double.class);
          o.setValue(value);
          return o;
     }

     public static Argument set(float value) {
          Argument o = new Argument(float.class);
          o.setValue(value);
          return o;
     }

     public static Argument set(int value) {
          Argument o = new Argument(int.class);
          o.setValue(value);
          return o;
     }

     public static Argument set(long value) {
          Argument o = new Argument(long.class);
          o.setValue(value);
          return o;
     }

     public static Argument set(short value) {
          Argument o = new Argument(short.class);
          o.setValue(value);
          return o;
     }
}

Now you can use the "set(...)" static method to wrap any Java native data type.


Hope this helps,
Doron
Avatar of ylyip

ASKER

Doron, thanks for your code. It is a generic wrapper class of primitive types. But it does not seem to solve my problem. If I have an unknown number of primitive values from a source, say a file, I still need to create a lot of objects if the Argument class is used.

The suggestion of bazarny to write a dynamic array class looks closer to the problem.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of girionis
No comment has been added lately, so it's time to clean up this TA.

I will leave a recommendation in the Cleanup topic area that this question is:

- split points between bazarny@idg and doronb

Please leave any comments here within the
next seven days.

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER !

girionis
Cleanup Volunteer