jitm
jitm

Reputation: 2597

Java Enums find enum

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.

Upvotes: 5

Views: 4382

Answers (5)

John Engelman
John Engelman

Reputation: 4439

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;
    }
}

Upvotes: 2

Hank Gay
Hank Gay

Reputation: 72039

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.

Upvotes: 4

Bozho
Bozho

Reputation: 597412

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.

Upvotes: 13

David Webb
David Webb

Reputation: 193814

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.

Upvotes: 2

Richard Fearn
Richard Fearn

Reputation: 25511

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.

Upvotes: 0

Related Questions