views:

104

answers:

3

Hi folks,

I am a newbie in this field so please excuse my silly mistakes :) So the issue I am facing is: On my webpage, I am displaying a table. For now my issue is concerned with three columns of the table.

    First is : Area Code
    Second is : Zone Code
    Third is: Value

The relationship between these three is:

1 Area Code has 6 different Zone code's and all those 6 Zone codes have corresponding "Value" I need a data structer that would give me the flexibility to get a "Value" for a Zone code, which falls under a particular Area code.

I have the same zone codes for all the Area codes:

   Zone codes are: 111, 222, 333, 444, 555, 666

After surfing your stackoverflow, I thought I can go with this structure:

    Map<Integer, Map<Integer, Double>> retailPrices = new HashMap<Integer, Map<Integer, Double>>();
    Map<Integer, Double> codes = new HashMap<Integer, Double>(); 

where reatailPrices would hold an Area Code and a Map of Zone code as Key and "Value" as Value.

but when I am trying to populate this through a SQL resultset, I am getting the following error:

The method put(Integer, Map<Integer,Double>) in the type Map<Integer,Map<Integer,Double>> is not applicable for the arguments (Integer, Double)

on line:

 while(oResult.next())

      retailPrices.put((new Integer(oResult.getString("AREA"))), (codes.put(new Integer(oResult.getString("ZONE_CODE")), new Double(oResult.getString("VALUE")))));


        }

please help me figure out this problem. Am I following the right approach?

+4  A: 

If these three items are related, I'd recommend creating an object that's meaningful for your problem and encapsulate them together:

public class Area
{
    private int areaId;
    private List<Zone> zones;

    // other code here
}

public class Zone
{
    private int zoneId;
    private double value;

    // other code here
}

That way you'd be able to use List<Area> in your code. You can also encapsulate any rules relating these that you wish.

Java's an object-oriented language. Stop thinking in terms of primitives and start thinking in terms of objects and encapsulation.

duffymo
That's close - remember he said that 1 Area has 6 different Zone codes. So you'd probably want "zone" above to be a List or array type.
Phil
Hi duffymo, Thanks for the reply. The only relation is the one I described above. I am very new to this, so it will be a big challenge to encapsulate it in one class :( The relationship is: 1 Area = {6 Zones = 6 values} so every area code has 6 zones, and these zones have 6 values. what am I doing wrong with adding values to that inner hashmap? Why that error?
techoverflow
+1: a custom class / value object / Javabean / DTO / POJO / whatever-you-like-to-call-it is the way to go.
BalusC
Then by all means make it a List. I just believe that if this is the relationship that's required, you should enforce such a thing in an object. A Map will not do this. Lift thyself out of the primitives gutter. Think about objects.
duffymo
+1  A: 

Well, the problem you are seeing

The method put(Integer, Map) in the type Map is not applicable for the arguments (Integer, Double)

is because your line inserting into retailPrices has

(new Integer(oResult.getString("AREA")))

as the key (an Integer) but

pegPlPrices.put(new Integer(...), new Double(...))

as the value.

The signature of method put in a Map type is

 V put(K key, V value)

You assumed it returned the map itself, but it actually returns the value you are placing into it. So the type of pegPlPrices.put(Integer, Double) is Double.

Bringing it all together, this means that you are trying to do this:

retailPrices.put(Integer, Double)

You need to break your line into two:

// do the put on pegPlPrices
pegPlPrices.put(new Integer(oResult.getString("ZONE_CODE")), new Double(oResult.getString("VALUE"))
// now add pegPlPrices into your map
retailPrices.put((new Integer(oResult.getString("AREA"))), pegPlPrices));

and that should fix it for you

I think the structure you chose, however, is not adequate for this. If each of your Zone Codes has an intrinsic and native Value that doesn't separate from it, then you may want to make the Zone Code into a class or an Enum, with the Value as a private member. Then you can get rid of 1 level of Maps.

Edited to add an Enum skeleton for Zone-Value

If you want to see what an Enum for Zone-Value would be, here is a sample:

public enum Zone
{
    private Integer zoneCode;
    private Double value;

    ZONE1( /* Integer, Double */ ),
    ZONE2( /* Integer, Double */ );

    public Integer getZone()
    {
       return zoneCode;
    }
    public Double getValue()
    {
       return value;
    }

    private Zone(Integer z, Double v)
    {
       zoneCode = z;
       value = v;
    }
}
Phil
Hi Phil, Thanks for the response. Could you please explain a bit more with your Enum solution? I didnt get the intrinsic and native value part you mentioned?
techoverflow
By that I meant if the Value is just another way of referring to your Zone (as it seems to be from the description) then you should not treat it as separate from the Zone, but rather as a property of it. An Enum solution works for this, as does a PDO (provided by duffymo).
Phil
Sorry, I forgot the Value is a Double. In that case it's not an alias for the Zone, but I still think that depending on the design constraints you may want to think about tying them together.
Phil
Hmmmmmm... I am confused now :( So map wont be a good choice at all?
techoverflow
+1  A: 

As you say you are new to this, I also suggest an abstraction. Even if you won't use it it will show you a bit of OO thinking :)

The areaCode and zoneCode together suggest a Location to me:

public class Location {
  private Integer zoneCode;
  private Integer areaCode;

  // getters and setters here

  // With an equals and hashCode (always implement BOTH or NONE)
  // they behave well in a Map, otherwise you can have the same location
  // twice if the same (zone, area) are in more than 1 object
  // NB these implementations don't like NULL areaCodes or zoneCodes
  public boolean equals(Object other) {
    if (other == null) return false;
    if (other == this) return true;

    if (other instanceof Location) {
      Location otherLocation = (Location)other;
      return (zoneCode == otherLocation.zoneCode) && (areaCode == otherLocation.areaCode);
    }
    return false;
  }

  public int hashCode() {
    return zoneCode.hashCode() + areaCode.hashCode();
  }
}

You could then have a

Map<Location, Double> localizedPrices = new HashMap<Location,Double>();

As said, have a look and ignore :)

extraneon