简体   繁体   中英

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

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

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

I'd like to add another map over the previous map, such that there is a key and its value will be the above map. Is this the correct data structure, and how do we implement it?

I want something like this shown below

Key         Value

B1          RtyName  ----> "weepn", "weepfnb", "eedgeft", "xbteehy"
            rtyRate ----->"deed", "ww", "terrty", "hteetyure"



B2          RtyName  ----> "SSSweepn", "wpefSSSnb", "GGeGdgeft", "xbteYYYYhy"
            rtyRate ----->"WWded", "wTeTYw", "YYYYtrerty", "IIIehttyure"

As shown above, only a new key is been introduced to the map, and its value is the previous map.

so it is like a Map<String, Map<String, List<String>>> whis becomes a complex data structure can i organise the data structure as for example one class containing a Map, so it will be like

Map<B1 , RtyName>
Map<B2 ,rtyRate>

and payer nae contain list of values such as

 RtyName  ----> "SSSweepn", "wpefSSSnb", "GGeGdgeft", "xbteYYYYhy"
  rtyRate ----->"deed", "ww", "terrty", "hteetyure"

so in the above structure complexity will be low since at the end for B1 i have to search key that wiil be RtyName and against payer name further i have to search values which will be "wpn", "wpfnb", "dgeft", "xbthy"

please advise whheteher map will be best or is there any other better data structure also to obtain this .

one data structure coming in my mind is of Guava's Table

  final Table<String, String, List<String>> values = HashBasedTable.create();
values.put("B1", "RtyName", Lists.newArrayList("weepn", "weepfnb", "eedgeft", "xbteehy"));
System.out.println(values.get("B1", "RtyName")); // prints the list

My objective is that any data structure I can have in which against B1 I will get Rtyname and for Rtyname I will get possible list of values

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

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, fe 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM