• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 833
  • Last Modified:

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.
0
ylyip
Asked:
ylyip
  • 12
  • 3
  • 3
  • +1
2 Solutions
 
Igor BazarnyCommented:
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
0
 
ylyipAuthor Commented:
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?
0
 
Igor BazarnyCommented:
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
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
ylyipAuthor Commented:
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.
0
 
Igor BazarnyCommented:

OK, but I'm still not sure that primitive-based HashMap would be helpful. Array is quite easy thing, try to stick with array as long as you can. Actually, you may create array of long's and use it for any primitives (check out Double.doubleToLongBits() method). Or array of ints and array of longs and use first one for floats, ints, chars and bytes and second for doubles and longs.

Possibly you need to review your algorithms. Do you really need all the data all the time? Maybe you can split your data into pieces, maybe you can put cache to the file. Check out java.nio package, new in 1.4 version, especially java.nio.channels.FileChannel for efficient file io.

Regards,
Igor Bazarny
0
 
doronbCommented:
0
 
doronbCommented:
0
 
doronbCommented:
0
 
doronbCommented:
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
0
 
doronbCommented:
0
 
doronbCommented:
0
 
doronbCommented:
0
 
doronbCommented:
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...
0
 
doronbCommented:
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...
0
 
doronbCommented:
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...
0
 
doronbCommented:
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
0
 
ylyipAuthor Commented:
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.
0
 
doronbCommented:
ylyip, if you combine my code with bazarny's you'd get something like this:

class Wrapper {

Argument cache = new Argument[100];

private int calculateIndex(XXXX value) {
   int index = -1;
   // Calculate the index for this specific type of data..
   return index;
}

public Argument wrap(XXXXX value) {
   // Find where the data should be..
   int index = calculateIndex(value);
   // Check to see if it's in the cache..
   if (index < 0 || index >= cache.length) {
      // Return a new wrapped Argument..
      return Argument.set(value);
   }
   // Is the cache entry empty?
   if (cache[index] == null) {
       // Create and store a new Argument..
       cache[index] = Argument.set(value);
   }
   return cache[index];
}

Of course you'll have to implement the wrap(...) and calculateIndex(...) methods for every native data type like I did in my Argument class, but using this wrapper ensures that you have a generic wrapper with caching for any data type.


Hope this helps,

Doron
0
 
girionisCommented:
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
0

Featured Post

How to Use the Help Bell

Need to boost the visibility of your question for solutions? Use the Experts Exchange Help Bell to confirm priority levels and contact subject-matter experts for question attention.  Check out this how-to article for more information.

  • 12
  • 3
  • 3
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now