[Question] Java Enums. Getting a Enum through a ID Field? Is it possible?

Discussion in 'Plugin Development' started by Flash619, May 22, 2012.

Thread Status:
Not open for further replies.
  1. Offline

    Flash619

    Well today I finally decided to convert these ugly mount arrays:
    Code:java
    1.  
    2. public static Integer[] Mounts = new Integer[]{
    3. //Enderdragon will no longer be listed here but
    4. //instead as a seperate config entity.
    5. 95,//Wo14lf
    6. 52,//Spider
    7. 90,//Pig
    8. 91,//Sheep
    9. 92,//Cow
    10. };
    11. public static String[] MountType = new String[]{
    12. //This must always be linked to the above table! THESE SHOULD ALWAYS BE REFERENCED FROM THE BUKKIT JAVA DOC OF ENTITY NAMES
    13. "WOLF",
    14. "SPIDER",
    15. "PIG",
    16. "SHEEP",
    17. "COW",
    18. };
    19. public static String[] MountName = new String[]{
    20. ////This must always be linked to the above table!
    21. "Wolf",
    22. "Spider",
    23. "Pig",
    24. "Sheep",
    25. "Cow",
    26. };
    27.  


    To a lovely Enum that looks 10x better:

    Code:java
    1.  
    2. /**
    3.  * @author Flash619
    4.  * (C)2012 Licensed under the GNU Lesser General Public License v3
    5.  */
    6. package com.github.flash619.MountUp.Core.StorageClasses;
    7.  
    8. public class MountsTable {
    9. public enum MountInfo{
    10. WOLF("Wolf",250,95),
    11. SPIDER("Spider",175,52),
    12. PIG("Pig",100,90),
    13. SHEEP("Sheep",50,91),
    14. COW("Cow",50,92);
    15.  
    16. String name;
    17. int speed;
    18. int id;
    19.  
    20. MountInfo(String name,int speed,int id){
    21. this.name=name;
    22. this.speed=speed;
    23. this.id=id;
    24. }
    25.  
    26. public int getSpeed(){
    27. return speed;
    28. }
    29. public int getId(){
    30. return id;
    31. }
    32. public String getName(){
    33. return name;
    34. }
    35. }
    36. }
    37.  


    But Now I have a bunch of methods, that point to get methods in a reference file, and they ALL use the ID as there key to get the data. Now a Enum uses a String name. So.... Lets say I wanted to get Wolf by its ID of 95. How would I go about doing this? Is it possible?

    I read up some things online but it seems a bit confusing to get a grasp on it, would definitely be helpful, and it seems that the bukkit community is always the right place to go for that. ^_^

    Thank you for your help, and a major thanks in advance! :D

    ~Flash619
     
  2. MountInfo.values()[index]
     
  3. You probably need to iterate through all of them and check every id.
    Something like this:
    Code:
    public MountInfo getMountByID(int id)
    {
        for(MountInfo mount : MountInfo.values())
        {
            if(mount.getId() == id)
                return mount;
        }
    }
     
  4. values() return an array, right, then you can you can also do:
    Code:java
    1. public MountInfo getMountByID(int id)
    2. {
    3. return MountInfo.values()[id];
    4. }
     
  5. Offline

    Flash619

    So then does that return the enum "mount"? Sorry I'm a bit new to enums. Also, would it be possible to have it return a specific part of the enum? Like name for instance?

    Hmnnn I'm trying to figure out which way would work better.......

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 25, 2016
  6. Well, his would work, but not in this context. the index of the enum in the array is not the id that you're searching for. That's why you need to iterate through them like i did.

    You have the enum instance, you can just call .toString() to get the name for example.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 25, 2016
  7. Offline

    Sagacious_Zed Bukkit Docs

    One of Bukkit's enums has a similar problem, they have a getById method which looks at a hashmap of the different enum values i think.
     
  8. Offline

    Flash619

    Oh wow, thanks a bunch ^_^ I understand how it works now xD

    I read up on that method I think, but someone had said it was only faster than casting it to an array if you had like 40 + values in it. :/

    Hmnn so I have a bit of a problem. I thought I understood this but I must have been mistaking.

    Code:java
    1.  
    2. String name = MountsTable.MountInfo.getMountByID(ID).getName();
    3.  


    Eclipse keeps saying that it can't cast from a int "ID" to a MountsTable.MountInfo

    :/

    Code:java
    1.  
    2. public static String getMountName(Integer ID){
    3. if(!ID.equals(null)){
    4. MountInfo info = MountInfo.getMountByID(ID);
    5. String name = info.getName();
    6. return name;
    7.  
    8. }return null;
    9. }
    10.  


    Seems to work. Is that correct?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 25, 2016
  9. it works totally fine using this enum:
    Code:
        public enum MountInfo{
            WOLF("Wolf",250,95),
            SPIDER("Spider",175,52),
            PIG("Pig",100,90),
            SHEEP("Sheep",50,91),
            COW("Cow",50,92);
     
            String name;
            int speed;
            int id;
     
            MountInfo(String name,int speed,int id){
                this.name=name;
                this.speed=speed;
                this.id=id;
            }
     
            public int getSpeed(){
                return speed;
            }
            public int getId(){
                return id;
            }
            public String getName(){
                return name;
            }
           
            public static MountInfo getMountByID(int id)
            {
                for(MountInfo mount : values())
                {
                    if(mount.getId() == id)
                        return mount;
                }
                return null;
            }
        }
    (I don't know how you implemented the method, but this implementation works fine.)
     
  10. Hint: ID.equals(null)
    ^^ that would throw an nullpointerException if ID is null, add checks to ensure its not null
     
  11. he does: there's a ! right in front of it.

    But it should be correct yes.
     
  12. then it also throw an NullPointerException
     
  13. Offline

    Flash619

    Well this works:
    Code:java
    1.  
    2. public static String getMountName(Integer ID){
    3. if(!ID.equals(null)){
    4. MountInfo info = MountInfo.getMountByID(ID);
    5. String name = info.getName();
    6. return name;
    7. }return null;
    8. }
    9.  


    Wait a min...
    Code:java
    1.  
    2. public static String getMountName(Integer ID){
    3. if(!ID.equals(null)){
    4. String name = MountInfo.getMountByID(ID).getName();
    5. return name;
    6. }return null;
    7. }
    8.  

    No longer gives me an error :confused:?? Possible that eclipse was glitching out with the previous error?

    It would appear that the second method would be more efficient.... I think..
     
  14. Actually ferrybig is right in the point that .equals(null) will still give you a NPE so you should use the equals operator (==) instead of the function.

    Both are basically the same when it comes down to efficiency.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 25, 2016
  15. Offline

    Flash619

    So if I expect it could equal null I should use "==" to see if its null "!=" to see if its not null

    and if I don't expect it to be null, I can continue to use .equals ?
     
  16. Offline

    desht

    Yep, that's the way to do it. Flash619 I just want to add one point: while it's not an issue in this example where you only have five values, a getByID() method could get pretty slow if your enum has many possible values. In that case, you probably want to initialise a HashMap lookup table for the ID->instance mapping.
     
    Acrobot likes this.
  17. Yeah, != is the way to go (I don't want to do every thinking for you ;D).
    if it's not null .equals would be fine, but we want to check whether it's not null, hence there shouldn't be an exeption if it's actually null, for some reason.
     
  18. Offline

    Flash619

    Thanks a bunch! :)

    So what your saying, is on load everything in the Enum should be converted to a hashmap?

    I did read that it can get slow when I was trying to research how to do this. Would there be any good examples that you would recommend I follow? I did find one with a hashmap once, but it looked a bit, complex for someone who just learned Enum's today -_-
     
  19. Well, like desht also said, it's not really necessary for such small amounts of enums. However, if you still want to learn how to do it, I'm gonna try to explain how I would achieve it.

    First, you'd need the hashmap inside your enum:
    Code:
    private static final Map<Integer, MountInfo> mountIds = new HashMap<Integer, MountInfo>();
    the final modifier doesn't really matter but to prevent it from being re-instaciated it's good to have. The static modifier however does matter. Otherwise we wouldn't even be able to use this sort of mapping.

    Since we never really create an instance of the enum (except inside it) we can't do the mapping in the real constructor. But there's something called static constructor which gets called without us noticing it. I don't know when it actually gets called so I can't give you more info on that. Using this static constructor we can create the mapping for later use. It's basically just a code block where we loop through the values and put them into the hash map:
    Code:
    static {
      for(MountInfo mount : values())
      {
          mountIds.put(mount.getId(), mount);
      }
    }
    Now we have mapped the id to the enum! Since the map is private we now only need a method to actually get the enum by it's id or modify the old method. It's basically just getting from the map:
    Code:
    public static MountInfo getMountInfoById(Integer id)
    {
        return mountIds.get(id);
    }
    And that's it! If you have any questions, feel free to post them!
     
    desht likes this.
  20. Flash619: Everything is fine now? Or still some questions?
     
Thread Status:
Not open for further replies.

Share This Page