[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 338
  • Last Modified:

data structure design

This question is 1/2 design, 1/2 java.

Suppose i have some variables, like this:

stooge (MOE, LARRY, CURLY)
height (TALL, MEDIUM, SHORT)
hair  (BALD, HIRSUTE)
wealth (POOR, AVERAGE, RICH)

This indicates, for example, that the variable stooge can be of value MOE, LARRY or CURLY
(doesn't matter what type of data it is, just any primitive)

I have many many data records which might look like this:

dataRecord:
  int i1;
  int i2;
  boolean b;
  String s;
  float f;

I would then write some code like so:

if (i1 / i2+ < 100)
  stooge = MOE;
else if (i1 / i2 == 100)
  stooge = LARRY
else
  stooge = CURLY

if (b == true) && (f < 10.0)
  height = tall
else (b == true && (f == 10.0)
  height = medium
else
  height = short

The point is that, with each record I can determine a value for each of stooge, height, hair and wealth.

I need to count the number of occurrences of each possible combinations, e.g. I need to count how many
(MOE, TALL, BALD, POOR) occurences there are.

What is the best way to create a data structure for this?


0
allelopath
Asked:
allelopath
  • 8
  • 5
  • 3
  • +2
2 Solutions
 
CPlusJavaCSharpCommented:
A loop? Let see you have a stack, queue, tree, graph...
0
 
allelopathAuthor Commented:
My first thought is a multidimensional array
int numberOfOccurences [3][3][2][3]
0
 
mkatmonkeyCommented:
A class to describe the stooge. A static method to generate a key based on the attributes and a hash map used to map the key to the count of instances.
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
allelopathAuthor Commented:
mkatmonkey:
When you say 'a class to describe the stooge', does Class Stooge contain height, hair and wealth?
0
 
mkatmonkeyCommented:
That's the idea.
0
 
CEHJCommented:
enum Stooge {
    MOE,
    LARRY,
    CURLY
}

etc.

Keep a Set of each variable that you can query
0
 
mkatmonkeyCommented:
You initial thought would work too, but the problem is two weeks later when stooges can have a dozen new attributes, you'd have a very large multidimensional array for counting the occurrences. Referencing them is error prone.

With the approach I suggested, you could just alter how you generate the key which is less error prone. Other benefits of this approach is just increased flexibility. For example, you can maintain multiple ways of counting and grouping your stooges.
0
 
allelopathAuthor Commented:
CEHJ:
I've never used a Set before. Could you provide a little more detail. I understand the enum part.
0
 
objectsCommented:
Expanding on what mkatmonkey mentioned earlier you would define a hashCode() and equals() method in your data record class and then stor4e all instances in a Map keyed on the object itself.

public class DataRecord {

   public int hashCode() {
       ....
   }

   public boolean equals(Object o) {
       ...
   }
   ...


Then in your code:

DataRecord record = new DataRecord(stooge, height, ...

Integer count = map.get(record);
if (count==null) {
   // new combo
   count = new Integer(0);
}
// incremement counter for this combo
map.put(record, new Integer(count.intValue()+1));
0
 
allelopathAuthor Commented:
objects:
thanks for the response. Something doesn't make sense to me, though.
You say:

DataRecord record = new DataRecord(stooge, height, hair,wealth);

but mkatmonkey suggested a new class (call it Stooge) with stooge, height, hair,wealth that is separate from the data record with members i1, i1, b,s,f. Do you mean, then to do this:

Stooge stooge = new Stooge(stooge, height, hair,wealth);

and have the hashcode() and equals() method in the Stooge class?

I think it is best to keep i1, i2, b,s,f separate from stooge, height, hair,wealth
0
 
allelopathAuthor Commented:
also, I am not clear on what hashCode() and equal() would contain.
0
 
objectsCommented:
> Stooge stooge = new Stooge(stooge, height, hair,wealth);
> and have the hashcode() and equals() method in the Stooge class?

sorry, yes thats what I meant.  Just got the naming mixed up
0
 
objectsCommented:
equals() would return true if all the properties are equal.
See the javadoc for hashCode() contract
http://mindprod.com/jgloss/hashcode.html

0
 
allelopathAuthor Commented:
Also, I don't understand where 'map' is coming from in your example.
Is this java.util.Map interface?
If so is it implemented by Stooge?


Something like this for equals() and hashcode(): --------------

public boolean equals(Object o)
{
if ( o == null )
{
  return false;
}
if ( (o.stooge == this.stooge) &&
     ( o.height == this.height) &&
     ( o.hair == this.hair) &&
     ( o.wealth == this.wealth) )
{
return true;
}
else
{
return false;
}

public int hashCode() {
  return this.hashCode();
}
0
 
objectsCommented:
> Is this java.util.Map interface?

yes

> If so is it implemented by Stooge?

No, you can use HashMap

Map map = new HashMap();

or using Java 5+

Map<Stooge, Integer> map = new HashMap<Stooge, Integer>();

It maps the number of instances of each stooge type.
0
 
allelopathAuthor Commented:
Ok, bear with me. I getting there.
I now have a class called StoogeHash which has the Map declared as you describe. Using the data records, it determines the values of stooge hair, height, wealth and then creates a new object:

StoogeEntry stoogeEntry = new StoogeEntry( stooge, hair, height, wealth );

Then, as you specify, it increments the count:

// see if this combination is already an entry is hashmap
Integer count = map.get( stoogeEntry );

// if not then we have a new entry, so start with zero count
if ( count == null ) {
    // new combination
    count = new Integer( 0 );
}

// increment counter for this combination
map.put( stoogeEntry, new Integer( count.intValue() + 1 ) );

The 'elemental' class is called StoogeEntry. It has the members stooge, hair, height, wealth with their getters/setters. It also has these 2 methods:

public int hashCode()
{
    int result = 17; // arbitrary value to start with
    result *= stooge.hashCode();
    result *= hair.hashCode();
    result *= height.hashCode();
    result *= wealth.hashCode();

    return result;
}

public boolean equals(StoogeEntry stoogeEntry)
{
  if ( ( this.getStooge() == stoogeEntry).getStooge() ) && ( this.getHair() == stoogeEntry.getHair() )
             && ( this.getHeight() == stoogeEntry).getHeight() )
             && ( this.getWealth() == stoogeEntry).getWealth() ) ) ) {
            return true;
  }
  else {
      return false;
 }
}

So after processing all data records, I will have a map with entries for each 'kind' of StoogeEntry.


How do I get the count for a specific combination?
0
 
objectsCommented:
Thats basiocally what u do in the first step.
You create a a StoogeEntry for the combo u require and call the maps get() method to get the count
0
 
allelopathAuthor Commented:
Ok, its working. I'm going to keep this question open for another week or so, in case I come across anything.
0

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

  • 8
  • 5
  • 3
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now