0

I have multidimensional double[][] arrays of which each element has a set of properties.

I designed these properties as a Class:

public class ElemProperties 
{
    public double prop1;

    ...     
}

Linking them with the elements of the array using a HashMap:

HashMap<double[][], ElemProperties> elemProperties; 

using it like e.g:

elemProperties.get(exampleArray).getProp1();

However, this only serves as a mapping between the whole array and properties. What I'm trying to do is to actually map the elements. Since Java doesn't have pointers, I'm kind of stuck at this position. This design seems very convoluted is there a better way to achieve this goal?

9
  • docs.oracle.com/javase/7/docs/api/java/util/Properties.html java.util.Properties? Commented May 21, 2015 at 13:56
  • 1
    It is very convoluted indeed. I would start thinking about objects rather than arrays and maps. Unfortunately I can't really make out the structure you want to achieve from the question. Commented May 21, 2015 at 13:56
  • @biziclop I tried to rephrase the question. I think you're right, I was just trying to avoid a major refactoring, trying to link the existing data structures. Commented May 21, 2015 at 14:00
  • I don't quite get your concept. Why do both the key and the value represent the properties? Commented May 21, 2015 at 14:01
  • 1
    You shouldn't use an array as the key to your Map, think about what would happen if the array changed. If the ElemProperties are properties for a specific value in your multidimensional array use Map<Double, ElemProperties> Commented May 21, 2015 at 14:03

3 Answers 3

2

First attempt would be:

public class Elem {
    private double value;
    private double additionalProperty1;
    private double additionalProperty2;
    ...
}

And create an Elem[][] instead of a double[][].

This at least works but multi-dimensional arrays aren't too efficient and aren't too expressive either, so the next question is whether you could group them using a different structure.

If the additional properties are optional or could be shared between multiple elements, you would need to write objects for them too, but the starting point is the same.


It is of course possible that you genuinely need a Map to link values to additional properties "because of reasons". In that case you can do something like this:

public class Container {
   private double[][] values;
   private Map<Double,AdditionalProperties> properties;

   public double getValue(int x, int y) {
     return values[x][y];
   }

   public AdditionalProperties getProperties(int x, int y) {
     return properties.get( getValue(x, y ) );
   }
 }

This way you can hide the fact that you use two separate data structures to store the data, and maintain data integrity between them.

Note though that this is semantically very different from the first solution. In particular, positions containing the same value will share their AdditionalProperties.

(There are also practical problems with this implementation, @dasblinkenlight already pointed out why using doubles as keys to a map is an issue, the other is that an autoboxing conversion happens and that can add some memory and run time overhead. All these problems can be overcome with careful coding, but I'm only demonstrating the basic concept here.)

Sign up to request clarification or add additional context in comments.

1 Comment

That's it, thanks! I feel silly for not having thought of this. It solves the problems that come from using primitives as elements when in fact I needed Objects to properly reference them.
2

since the HashMap compares for references this works.

Comparing for references also happens to be the biggest problem with this approach: the fact that the object is a 2d array of double does not matter - one could simply replace your map with

HashMap<Object,ElemProperties> elemProperties;

without losing any functionality.

A better approach would be making a class that represents 2D keys based on arrays of double:

class KeyDouble2D {
    private final double[][] key;
    public KeyDouble2D(double[][] key) {
        // Make a copy of key into this.key
    }
    public boolean equals(Object other) {
        // Ensure that other is KeyDouble2D, then compare key
        // sizes, and finally compare arrays element-by-element.
        // Make sure to use `Double.equals` method to avoid NaN != NaN problem.
    }
    public int hashCode() {
        // Compute hash code as a sum of hash codes in 2D array
    }
}

You can use this class for keys of your hash map:

HashMap<KeyDouble2D,ElemProperties> elemProperties = ...;
...
ElemProperties prop = elemProperties.get(new KeyDouble2D(exampleArray)).getProp1();

Note that one needs to be very careful when using arrays of double for hash keys, for the same reason why one needs to be careful when comparing doubles for equality.

Comments

2

Why not create a class DoubleWithProperties, and manipulate an array of this class, instead of using a hashmap?

class DoubleWithProperties {
   double value;
   ElemProperties props;
   public DoubleWithProperties(double value, ElemProperties props){
   ...
   }
}
DoubleWithProperties[][] array = new DoubleWithProperties[5][5];

1 Comment

Thanks, I think this is the simplest approach.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.