Choosing the data structure for orgaininsng data with list of values in java

前端 未结 2 1490
盖世英雄少女心
盖世英雄少女心 2021-01-19 06:27

I have a map as shown below in which there is a key and values is of type List:

Map newdatamap = new HashMap<&g         


        
相关标签:
2条回答
  • 2021-01-19 07:00

    I would do this:

    Map<Integer, List<String>> dataMap = new HashMap<>();
    dataMap.put("B1".hashCode()+"RtyName".hashCode(), Arrays.asList("weepn", "weepfnb", "eedgeft", "xbteehy"));
    dataMap.put("B1".hashCode()+"rtyRate".hashCode(), Arrays.asList("deed", "ww", "terrty", "hteetyure"));
    dataMap.put("B2".hashCode()+"RtyName".hashCode(), Arrays.asList("SSSweepn", "wpefSSSnb", "GGeGdgeft", "xbteYYYYhy"));
    dataMap.put("B2".hashCode()+"rtyRate".hashCode(), Arrays.asList("WWded", "wTeTYw", "YYYYtrerty", "IIIehttyure"));
    

    Which would represent:

    B1, RtyName  ----> "weepn", "weepfnb", "eedgeft", "xbteehy"
    B1, rtyRate ----->"deed", "ww", "terrty", "hteetyure"
    
    B2, RtyName  ----> "SSSweepn", "wpefSSSnb", "GGeGdgeft", "xbteYYYYhy"
    B2, rtyRate ----->"WWded", "wTeTYw", "YYYYtrerty", "IIIehttyure"
    

    Note that hashCode is just a convient function from the String class that meets my needs. You could roll your own that returns a String key (or really anything else) if you preferred.

    Actually since your original method didn't require an order independent function, you could really even concatenate the String keys to use as a new key:

    dataMap.put("B1"+"RtyName", Arrays.asList(/*your list here*/));
    

    This is a little less convenient (and not as "good" programmatically) than the first method, but still much better than nesting Map classes. (And makes keys much easier to recognize when outputted than hashCode.)

    Two-way Mapping

    Values as Keys

    If you want each List value to map to keys as well as the other way around, you need a second Map:

    Map<List<String>, String> valueMap = new HashMap<>(); //New map for value->key 
    for(String key: dataMap.keySet()) //Get all keys
        valueMap.put(dataMap.get(key), key); //Create mapping value->key
    

    Each Item in Value as a Key

    If you want each String item in the values list to map to keys as well as the other way around, you need a second Map:

    Map<String, String> itemMap = new HashMap<>(); //New map for item->key mapping
        for(String key: dataMap.keySet()) //Get all keys and iterate through
            for(String item: dataMap.get(key)) //For each item in your value list
                itemMap.put(item, key); //Create new mapping item->key
    
    0 讨论(0)
  • 2021-01-19 07:16

    As you asked for it:

    You simply define a class, ABC in this case as you've suggested that name, which holds two lists, the RtyName and the rtyRate list:

    public class ABC {
        private List<String> RtyName;
        private List<String> rtyRate;
    
        public ABC(List<String> RtyName, List<String> rtyRate) {
            setRtyNames(RtyName);
            setRtyRates(rtyRate);
        }
    
        public void setRtyNames(List<String> RtyName) {
            this.RtyName = RtyName;
        }
    
        public List<String> getRtyNames() {
            return this.RtyName;
        }
    
        public void setRtyRates(List<String> rtyRate) {
            this.rtyRate = rtyRate;
        }
    
        public List<String> getRtyRates() {
            return this.rtyRate;
        }
    }
    

    Once this class is ready, you can change your map definition to:

    Map<String, ABC> newdatamap = new HashMap<>();
    

    And assign new values to it similar as you already did before - instead of nesting those lists in a further map and putting this map into the outer map though, you create a new instance of ABC, provide the two lists as input parameter and put the resulting ABC object into the map (formally the outer map):

    List<String> RtyName = Arrays.asList("wpn", "wpfnb", "dgeft", "xbthy");
    List<String> rtyRate = Arrays.asList("dd", "ww", "trrty", "httyure");
    newdatamap.put("B1", new ABC(RtyName, rtyRate));
    

    You could also assign those lists directly as input-parameters:

    newdatamap.put("B2", new ABC(Arrays.asList("SSSweepn", "wpefSSSnb", "GGeGdgeft", "xbteYYYYhy"), 
                                 Arrays.asList("WWded", "wTeTYw", "YYYYtrerty", "IIIehttyure"));
    

    An entry is now simply retrieved on calling get(String) as you already used to do:

    ABC data = newdatamap.get("B1);
    

    You can also retrieve one of the lists directly like:

    List<String> RtyNames = newdatamap.get("B1").getRtyNames();
    

    In my opinion this is way easier to manage and to read at the same time. On top of that, you gain also runtime-saftiness as you do not run into eventual typing errors for RtyName or rtyRate.

    Update for redesign

    If RtyName entries and rtyRate entries always go hand in hand, f.e. wpn is the name and dd is the assigned rate, grouping those fields together would make sense. Therefore you could refactor your code to furthermore reduce one list and introduce a new class:

    public class RtyEntry {
        private String name;
        private String rate;
    
        public RtyEntry(String name, String rate) {
            setName(name);
            setRate(rate);
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getName() {
            return this.name;
        }
    
        public void setRate(String rate) {
            this.rate = rate;
        }
    
        public String getRate() {
            return this.rate;
        }
    }
    

    If you now change ABC to only contain one list of RtyEntry objects like this:

    public class ABC {
        private List<RtyEntry> rtyEntries;
    
        public ABC(List<RtyEntry> rtyEntries) {
            this.rtyEntries = rtyEntries;
        }
    
        public ABC() {
            this.rtyEntries = new ArrayList<>();
        }
    
        public void setRtyEntries(List<RtyEntry> rtyEntries) {
            this.rtyEntries = rtyEntries;
        }
    
        public List<RtyEntry> getRtyEntries() {
            return this.rtyEntries;
        }
    
        // convenience methods
    
        public void addRtyEntry(RtyEntry entry) {
            this.rtyEntries.add(entry);
        }
    }
    

    The creation would now change to:

    RtyEntry entry1 = new RtyEntry("wpn", "dd");
    List<RtyEntry> entries = Arrays.asList(entry1, ...);
    newdatamap.put("B1", new ABC(entries));
    

    You can then also assign new entries like that:

    newdatamap.get("B1").addRtyEntry(new RtyEntry("wpfnb", "ww"));
    

    Retrieving entries also changed to the refactoring:

    ABC data = newdatamap.get("B1");
    List<RtyEntry> entries = data.getRtyEntries();
    for (RtyEntry entry : entries) {
        System.out.println(entry.getName() + " has a rate of: " + entry.getRate());
    }
    

    Of course you can also retrieve the list directly via:

    List<RtyEntry> entries = newdatamap.get("B1").getRtyEntries();
    

    as before.

    0 讨论(0)
提交回复
热议问题