Java - Keeping 2 keys for one value (TreeMap) - java

I was trying to create a composite key of Type and Name both return String
public String getObjectName() {
return objectName;
}
public String getObjectType() {
return objectType;
}
and would like to store it in Treemap
both objectName and objectType needs to be a single key and the second String i.e value need to be a user specified Value of Type String
what are your suggestions on this?
This is where I'm gonna store the TreeMap
public static void setDomainDocumentationMap(Map<String, String> domainDocumentationMap) {
MMTUtil.domainDocumentationMap = domainDocumentationMap;

One way is to concatenate as shown in other answers. Then you can use them as key, and in value, put whatever user input is.
This leads to Map<String, String> type.
Another way is to create a class for key:
class Key{
private String objectName;
private String objectType;
//TODO write setters here
public String getObjectName(){
return objectName;
}
public String getObjectType(){
return objectType;
}
public String toString(){
return objectName + ":separator:" + objectType;
}
//TODO implement hashcode and equals method
}
Now your map should be: Map<Key, String> and I believe this should be more flexible.

You can concatenate the two prospective keys with a string like "##-#-#-##" or any other string which you are sure won't be there in your data, and make this concatenated string as the 'key' of your map.
In future if you need to retrieve the two key string from the 'key' of the map, just split the map's key using the "##-#-#-##" string.

As TreeMap is ultimately a map only, It will have same structure i.e key and value.
Only thing that is different is :A tree map guarantees that its elements will be sorted in an ascending key order. You want two Strings as composite key then You can Add any separator between these two strings and then add it as a key.
For example if we use # as separator it would be string1#string2 as key and against it there will be it's value stored.
Code Example :
public class Test{
private static final String SEPERATOR ="$$" ;
private String getCompositekey(String key1, String key2)
{
return key1+SEPERATOR+key2;
}
public static void main(String[] args){
Map<String,Object> t = new TreeMap<String,Object>();
Test test = new Test();
t.put(test.getCompositekey(test.getObjectName(),test.getObjectType()),VALUEGOESHERE);
}
}

Related

Match Java Map keyset values with String values of a Java list of objects

I have a Java list of objects which each one contains a String value (code). Also I have a Java Map. I want to check whether all the elements in the Map keys are included in the list of the String values.
The Model class :
public class Obj {
private String code;
private String name;
private String uom;
public Obj(String code, String name, String uom) {
this.code = code;
this.name = name;
this.uom = uom;
}
}
the implemention :
private static final Obj weight = new Obj("weight", "Weight", "Kg");
private static final Obj height = new Obj("height", "Height", "cm");
public static final List<Obj> objMasters = List.of(weight, height);
Set<String> keySet = map.keySet(); // returns the keyset values from the Map
boolean match =objMasters.stream()
.anyMatch(objMaster -> objMaster.getCode().matches(keySet.toString()));
But with this implementation I always get false as the value for the match. What has gone wrong here?
From what I now understood about your question, try this.
List<String> codes = objMasters.stream().map(obj -> obj.getCode()).collect(Collectors.toList());
boolean match = codes.containsAll(keySet);
0,when you use collection or map,please override equals and hashCode methods
/n1,you can deep study of source code like get() contain() and others methods
/n2, by then you will undunderstand why

Loading from csv and storing in HashMap with key containing multiple values

I have a hashmap that is storing values from a csv file. The file consists of three columns: TEMPLATE_NAME, PARAM_1, PARAM_2
I've been trying to use TEMPLATE_NAME as the key and PARM_1, PARAM_2 as the values for each row. The problem is that there may be many TEMPLATE_NAME with a different mix of params. My requirement specifies that a list of TEMPLATE_NAMES should be displayed when a PARAM_1 and PARAM_2 is selected.
I know that a hashmap cannot have duplicate keys so the hashmap is only creating one TEMPLATE_NAME key with values but ignoring the duplicates. How do I resolve this?
private void load() throws IOException{
CsvReader reader = new CsvReader();
List<List<String>> rows = reader.parse(csvFile);
for (int i = 1 ; i<rows.size() ; i++){
List<String> columns = rows.get(i);
String templateName = columns.get(TEMPLATE_NAME);
OnConfig config = entries.get(templateName);
if (config == null){
config = new OnConfig(templateName);
entries.put(templateName, config);
}
config.put(columns.get(PARAM_1), columns.get(PARAM_2));
}
}
public class OnConfig {
private final String templateName;
private final HashMap<String, String> attributes = new HashMap<>();
public OnConfig(String templateName){
this.templateName= templateName;
}
public void put(String param1, String param2){
attributes.put(param1, param2);
}
public String get(String param1){
return attributes.get(param1);
}
public String getTemplateName() {
return templateName;
}
#Override
public String toString() {
return String.format("Template Name: %s, Number of Attributes: %s", getTemplateName(), attributes.value());
}
}
The problem is that there may be many TEMPLATE_NAME with a different mix of params.
Create a new class representing TEMPLATE_NAMES and containing a List or Map of PARM_1, PARAM_2
Use a nested data structure. For instance, Nest a Map inside a Map: the outer keys are the TEMPLATE_NAMES, and inner key is PARAM_1

Use Collections to order ArrayList<HashMap<String,String>> comparing piece of string

I need sort ArrayList of HashMap, this is my code:
ArrayList<HashMap<String,String>> fiduList = new ArrayList<HashMap<String,String>>();
for (MapPoint aList: MapPointsList) {
HashMap<String, String> fidu = new HashMap<String, String>();
fidu.put(KEY_NAME, aList.getRealname());
fidu.put(KEY_TYPE, aList.getType());
fiduList.add(fidu);
}
getRealname get a string like this: AABB/CCCC/DDDD. For example:
AA11/4352/G435;
AA23/0234/J543;
AA02/0032/K123;
I need sort ArrayList comparing first DDDD, CCCC and then BB.
With my code I can sort only all string:
Collections.sort(fiduList, new Comparator<HashMap<String,String>>(){
public int compare(HashMap<String,String> mapping1,HashMap<String,String> mapping2){
return mapping1.get(KEY_NAME).compareTo(mapping2.get(KEY_NAME));
}
});
How can I solve the problem? (I'm new Java user).
Thank
I would suggest another approach. It seems that you use the map for holding two properties of an object - a name and a type. If so, a map is not the appropriate data structure.
You really should create an own class for it:
public final class Fidu {
private final String name;
private final String type;
public Fidu(String name, String type) {
this.name = name;
this.type = type;
}
}
When continuing to analyze the requirements, it seems as if the name consists of three parts, which must be parsed from a delimited string. Thus, your class should reflect that (note the private constructor and the factory method):
public final class Fidu {
private final String namePart1;
private final String namePart2;
private final String namePart3;
private final String type;
private Fidu(String namePart1, String namePart2, String namePart3, String type) {
this.namePart1 = namePart1;
this.namePart2 = namePart2;
this.namePart3 = namePart3;
this.type = type;
}
public static Fidu parse(String name, String type) {
String[] parts = name.split("/");
if (parts.length != 3)
throw new IllegalArgumentException(name);
return new Fidu(parts[0], parts[1], parts[2], type);
}
}
And finally, you should consider a natural ordering on the objects of type Fidu:
public final class Fidu implements Comparable<Fidu> {
...
public int compareTo(Fidu other) {
// an example:
int compare = this.namePart3.compareTo(other.namePart3);
if (compare != 0)
return compare;
compare = this.namePart2.compareTo(other.namePart2);
if (compare != 0)
return compare;
return this.namePart1.compareTo(other.namePart1);
}
}
Additionally this class obviously should also provide an implementation for hashCode and equals. Up to you ...
With that approach you do not need an ArrayList<HashMap<String, String>> anymore, but simply use a List<Fidu> (by the way, for the variable's types always use the interface and not an implementation). This list can then easily be sorted with
List<Fidu> fiduList = ...
Collections.sort(fiduList);
Change your sort from:
return mapping1.get(KEY_NAME).compareTo(mapping2.get(KEY_NAME));
To this:
String[] leftStrings = mapping1.get(KEY_NAME).split("/");
String[] rightStrings = mapping2.get(KEY_NAME).split("/");
int comp = 0;
for (int i = leftStrings.length - 1; i >=0; i--) {
comp = leftStrings[i].compareTo(rightStrings[i]);
if (comp != 0) {
break;
}
}
return comp;
This breaks your string into the three parts, then sorts the strings alphabetically working backwards. The first time we see a mismatch, we report the sort order.
In your Comparator#compare method you can use the class java.util.regex.Pattern to split up the real name using regular expressions:
Pattern pattern = Pattern.compile("(\\w{2})(\\w{2})/(\\w{4})/(\\w{4})");
Matcher matcher = pattern.matcher(realName);
if (matcher.matches()) {
String aa = matcher.group(1);
String bb = matcher.group(2);
String cccc = matcher.group(3);
String dddd = matcher.group(4);
// TODO: compare
} else {
// TODO: real name does not match pattern
}
Notes:
You need to compile the pattern only once (first line); it can then be reused. E.g put it into a static or non-static member variable.
\\w matches the following characters: 'a'-'z', 'A'-'Z', '0'-'9', '_'. If that's not sufficient, use other charachter classes or directly specify a custom character class like [A-Z0-9]
Extend TreeMap create your own map class, In this class provide your way to sort the Map objects, for your string comparisons you can pass the Comparator with your custom logic to TreeMap class.
http://docs.oracle.com/javase/7/docs/api/java/util/TreeMap.html
This way all the functionality of the Map will be available to you and you can also implement your own logic of sorting.

Java Collection with index, key and value

My question might sound silly, but would like to know whether there are any Collection object in Java that does store index,key and values in a single Collection object?
I have the following:
Enumeration hs = request.getParameterNames();
LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<String, String>();
while (hs.hasMoreElements()) {
linkedHashMap.put(value, request.getParameter(value));
}
The above stores key and value in linkedHashMap, but it doesn't have an index. If it has then I could call by index(pos) and get corresponding key and value.
Edit 1
I would want to conditionally check if index(position) is x then get the corresponding key and value pair and construct a string with query.
As mentioned by others, Java collections does not support this. A workaround is Map<R, Map<C, V>>. But it is too ugly to use.
You can go with Guava. It provides a Table collection type. It has the following format Table<R, C, V>. I haven't tried this but I think this will work for you.
Enumeration hs = request.getParameterNames();
Table<Integer, String, String> table = HashBasedTable.create();
while (hs.hasMoreElements()) {
table.put(index, value, request.getParameter(value));
}
Now, if you want key, value pair at, let's say, index 1. Just do table.row(1). Similarly, to get index, value pairs just do table.column(value).
No Collection in java, will support this.
You need to create a new class IndexedMap inheriting HashMap and store the key object into the
arraylist by overriding put method.
here is the answer(answerd by another user: Adriaan Koster)
how to get the one entry from hashmap without iterating
Maybe you need implementing yourself for achieving this functionality.
public class Param{
private String key;
private String value;
public Param(String key, String value){
this.key = key;
this.value = value;
}
public void setKey(String key){
this.key = key;
}
public String getKey(){
return this.key;
}
public void setValue(String value){
this.value = value;
}
public String getValue(){
return this.value;
}
}
Enumeration hs = request.getParameterNames();
List<Param> list = new ArrayList<Param>();
while (hs.hasMoreElements()) {
String key = hs.nextElement();
list.add(new Param(key, request.getParameter(key)));
}
By doing this, you could get param with an index provided by List API.

Sorting an arraylist of hashmap according to a value field of the hashmap

Basically, I have an arraylist declared like :
private ArrayList<HashMap<String, String>> songsList =
new ArrayList<HashMap<String, String>>();
now what I want to do is that for each key I want to give two value fields. Can it be done??
Secondly I want to sort the key-value pair according to the value pair. So how can it be achieved?
That's a lot of String objects. Have you considered encapsulating your data structure using an Object, rather than a complex collection of strings? For example, assuming your map key is a song:
public Song implements Comparable<Song> {
private String title;
private String artist;
private String album;
public Song(String title, String artist, String album) {
...
}
public int compareTo(Song s) {
// sorting logic
}
... // getters, setters, equals & hashCode
}
Then, create your list of songs:
List<Song> songs = new ArrayList<Song>();
songs.add(new Song("Dancing Queen", "Abba", "Arrival"); // I had to find this on Wikipedia
...
Then sort them:
Collections.sort(songs);
You can implement the comparable interface for the sorting problem of yours. And for having multiple values for a value in a map, create a class with the required values with getters and setters. And use the class as a value against the key.

Categories

Resources