Search code examples
javalistsortingmemoryhashmap

Java - Storing Sorted List Values in Memory


Quick Explanation:

I have a Hashmap that stores lists in different orders depending on their sortType. I want this to be stored in memory so that I don't have to sort each list on runtime, many times over which would be causing a lot of strain on CPU usage.

Currently I have a general HashMap that stores all items with their corresponding ID...

private Map<String, Cosmetic> cosmeticIDs;

I then store each of these IDs in a list which has been sorted based on the sortType and inserted into a HashMap as shown below...

public enum SortType {
    ALPHABETICALLY,
    ALPHABETICALLY_REVERSE,
    RARITY,
    RARITY_REVERSE;
}
        // List of Strings is the ID of each item
    private EnumMap<SortType, List<String>> availableTrailsIDs;
    private EnumMap<SortType, List<String>> availableGadgetsIDs;
    private EnumMap<SortType, List<String>> availableSuitsIDs;
    private EnumMap<SortType, List<String>> availablePetsIDs;

I then use the following to get the sorted map on runtime:

List<String> gadgets = availableGadgets.get(sortType);

for (String gadgetID : gadgets.subList(min, max)) {
   Cosmetic gadget = CosmeticHandler.getInstance().getCosmeticFromID(gadgetID);
   // LOAD GADGETS IN ORDER
}

Is there a better way of doing this? It seems like this a massive design flaw and is wasting a ton of memory.


Solution

  • SortedSet#subSet & NavigableSet#descendingSet

    Use SortedSet#subSet & NavigableSet#descendingSet. Both of these methods return a view onto the original set, without creating a separate collection.

    The concrete class TreeSet implements both of those interfaces. (TreeSet also implements SequencedSet now in Java 21+. See JEP 431.)

    public enum SortType {
        ALPHABETICALLY(new TreeSet<String>(/*you can have custom comparator Comparator.comparing... so you can use the cosmetic*/)) {
    
            @Override
            public Set<String> getSubSet(String min, String max) {
                return set.subSet(min, max);
            }
            
        },
        ALPHABETICALLY_REVERSE(ALPHABETICALLY.set) {
    
            @Override
            public Set<String> getSubSet(String min, String max) {
                return set.descendingSet().subSet(min, max);
            }
            
        },
        RARITY(new TreeSet<String>(/*you can have custom comparator Comparator.comparing... so you can use the cosmetic*/)) {
    
            @Override
            public Set<String> getSubSet(String min, String max) {
                return set.subSet(min, max);
            }
            
        },
        RARITY_REVERSE(RARITY.set) {
    
            @Override
            public Set<String> getSubSet(String min, String max) {
                return set.descendingSet().subSet(min, max);
            }
            
        };
        
        protected TreeSet<String> set;
        
        private SortType(TreeSet<String> set) {
            this.set = set;
        }
        
        public void add(String o) {
            set.add(o);
        }
        
        public abstract Set<String> getSubSet(String min, String max);
    
    }
    

    you have to retain now only to copy of the set, depending on the order adding itemes to both the TreeSets.