Reputation: 89
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
Upvotes: 4
Views: 179
Reputation: 9093
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
.)
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
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
Upvotes: 1
Reputation: 12849
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.
Upvotes: 0