tags:

views:

136

answers:

6

Hello, I've just read tutorial about enums and have one question. I've studied example:

public enum Planet {
    MERCURY (3.303e+23, 2.4397e6),
    VENUS   (4.869e+24, 6.0518e6),
    EARTH   (5.976e+24, 6.37814e6),
    MARS    (6.421e+23, 3.3972e6),
    JUPITER (1.9e+27,   7.1492e7),
    SATURN  (5.688e+26, 6.0268e7),
    URANUS  (8.686e+25, 2.5559e7),
    NEPTUNE (1.024e+26, 2.4746e7),
    PLUTO   (1.27e+22,  1.137e6);

    private final double mass;   // in kilograms
    private final double radius; // in meters
    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
    }
    public double mass()   { return mass; }
    public double radius() { return radius; }

    // universal gravitational constant  (m3 kg-1 s-2)
    public static final double G = 6.67300E-11;

    public double surfaceGravity() {
        return G * mass / (radius * radius);
    }
    public double surfaceWeight(double otherMass) {
        return otherMass * surfaceGravity();
    }
}

and question: How can I find enum type for example MERCURY if I know mass and radius ? Thanks.

+3  A: 

Give the Planet enum a static search method that accepts those two facts and looks it up. For something this size, a simple linear probe strategy should be plenty fast enough.

Hank Gay
Specifically, a *static* search method.
StriplingWarrior
Good point; I had assumed it was understood, but better to be explicit.
Hank Gay
+8  A: 

O(n) - iterate all enum values and compare:

for (Planet planet : Planet.values()) {
   if (..) {..}
}

The best place to put this is as a static method in the enum class itself.

Bozho
Thanks a lot, yes it works.
jitm
Thank you for confirming the stability of the Java language.
Erick Robertson
A: 

You need to write a static method that iterates on all enum values, test if the given mass and radius are equals to mass and radius from the current value, and, if equals, return the enum value.

Something like:

public static Planet fromMassAndRadius(double mass, double radius) {
    for (Planet planet : Planet.values()) {
        if (planet.mass == mass && planet.radius == radius) {
            return planet;
        }
    }
    return null;
}
Vivien Barousse
Be very careful comparing doubles with ==.
Darron
A: 

You can get an array of all the Planets using Planet.values(), and iterate through them, looking for the one that has the specified mass and radius.

Richard Fearn
+2  A: 

For an enum the values() method will return an array containing all of the values of the enum in the order they are declared. So you can just loop over the array looking for the Planet that matches your criteria.

for (Planet p : Planet.values()) {
    if (p.mass() == searchMass && p.radius == searchRadius) {
      //do something with p
    }
}

An enum is unlikely to have a large number of values so this will usually be fine performance wise.

Dave Webb
You should be careful comparing doubles with ==.
Darron
+1  A: 

The linear search patterns discussed are ideal for the posed problem. However, in the situation were the enum class grows (or if you're using pre-Java 1.5 type-safe enums using EnumSyntax to create run-time configured enums) you might want something a little faster. In that case, you could define a static initialization block that populates a Map with the values so you can look up by key-value pairs. In this case you would define Map> which is keyed by the mass then the radius. You would then provide a static method that returns the lookup from the map.

This is overkill is most circumstances since the linear search is more than sufficient for performance. But if you're perform these look-ups multiple times, then this solution provides a one-time hit at initialization.

Example Code:

public enum Planet {
MERCURY (3.303e+23, 2.4397e6),
VENUS   (4.869e+24, 6.0518e6),
EARTH   (5.976e+24, 6.37814e6),
MARS    (6.421e+23, 3.3972e6),
JUPITER (1.9e+27,   7.1492e7),
SATURN  (5.688e+26, 6.0268e7),
URANUS  (8.686e+25, 2.5559e7),
NEPTUNE (1.024e+26, 2.4746e7),
PLUTO   (1.27e+22,  1.137e6);

static {
   map = new HashMap<Double, Map<Double, Planet>>();
   for (Planet p : Planet.values()) {
      if (!map.containsKey(p.getMass())) {
         p.put(p.getMass(), new HashMap<Double, Planet>());
      }
      p.get(p.getMass()).put(p.getRadius(), p));
   }
}

private final double mass;   // in kilograms
private final double radius; // in meters

private static final Map<Double, Map<Double, Planet>> map;

Planet(double mass, double radius) {
    this.mass = mass;
    this.radius = radius;
}
public double mass()   { return mass; }
public double radius() { return radius; }

// universal gravitational constant  (m3 kg-1 s-2)
public static final double G = 6.67300E-11;

public double surfaceGravity() {
    return G * mass / (radius * radius);
}
public double surfaceWeight(double otherMass) {
    return otherMass * surfaceGravity();
}

public static Planet getPlanet(double mass, double radius) {
   if (map.contains(mass)) {
      return map.get(mass).get(radius);
   }
   return null;
}

}

John Engelman